Version Description
- Fixing interface.
Download this release
Release Info
Developer | dd@sucuri.net |
Plugin | Sucuri Security – Auditing, Malware Scanner and Security Hardening |
Version | 1.6.8 |
Comparing to | |
See all releases |
Code changes from version 1.6.6 to 1.6.8
- inc/css/sucuriscan-default-css.css +7 -7
- inc/js/sucuriscan-scripts.js +2 -2
- inc/tpl/integrity-corefiles.html.tpl +69 -29
- inc/tpl/integrity-corefiles.snippet.tpl +5 -5
- inc/tpl/integrity.html.tpl +0 -2
- inc/tpl/malwarescan.html.tpl +1 -1
- inc/tpl/setup-notice.html.tpl +2 -2
- readme.txt +8 -1
- sucuri.php +303 -104
inc/css/sucuriscan-default-css.css
CHANGED
@@ -146,7 +146,7 @@ div.sucuriscan-alert > a.close{position:absolute;top:10px;right:10px;font-size:1
|
|
146 |
.sucuriscan-scanner-results .sucuriscan-scanner-links tr:nth-child(even){background:#f5f5f5}
|
147 |
.sucuriscan-scanner-results td.sucuriscan-border-bad{border-left-width:4px;border-left-style:solid}
|
148 |
/* Integrity Styles */
|
149 |
-
.sucuriscan-status-type{width:20px;background:#ddd;text-align:center;text-transform:uppercase;margin-right:10px;padding:0 3px;border:1px solid transparent;border-radius:3px}
|
150 |
.sucuriscan-status-added{background:#dff0d8;color:#3c763d;border-color:#d6e9c6}
|
151 |
.sucuriscan-status-modified{background:#fcf8e3;color:#8a6d3b;border-color:#faebcc}
|
152 |
.sucuriscan-status-removed, td.sucuriscan-corefiles-warning > div{background:#f2dede;color:#a94442;border-color:#ebccd1}
|
@@ -154,13 +154,17 @@ div.sucuriscan-alert > a.close{position:absolute;top:10px;right:10px;font-size:1
|
|
154 |
.sucuriscan-maincontent .sucuriscan-integrity-message,
|
155 |
.sucuriscan-maincontent .sucuriscan-wordpress-outdated,
|
156 |
.sucuriscan-maincontent .sucuriscan-auditlogs{margin-top:0;margin-bottom:20px}
|
157 |
-
.sucuriscan-
|
158 |
-
.sucuriscan-corefiles-abbrs .sucuriscan-status-type{display:inline-block;width:initial;font-size:12px;text-transform:capitalize;float:left;margin-top:4px;margin-right:5px}
|
159 |
.sucuriscan-maincontent td.sucuriscan-corefiles-warning, .sucuriscan-maincontent td.sucuriscan-corefiles-warning p{margin:0;padding:0}
|
160 |
.sucuriscan-maincontent td.sucuriscan-corefiles-warning div{padding:10px;border-width:1px;border-style:solid}
|
161 |
.sucuriscan-maincontent td.sucuriscan-corefiles-warning code{font-size:12px;padding:0 5px}
|
162 |
.sucuriscan-maincontent .sucuriscan-integrity-message{position:relative}
|
163 |
.sucuriscan-maincontent .sucuriscan-integrity-message .sucuriscan-integrity-mark{position:absolute;top:1px;right:1px;background:#7ad03a;font-weight:bold;color:#fff;line-height:35px;padding:0 10px;border-left:1px solid #ddd}
|
|
|
|
|
|
|
|
|
|
|
164 |
/* Monitoring Styles */
|
165 |
.sucuriscan-monitoring-settings{margin-bottom:20px}
|
166 |
.sucuriscan-monitoring-settings td.td-with-button{text-align:left}
|
@@ -212,11 +216,7 @@ div.sucuriscan-alert > a.close{position:absolute;top:10px;right:10px;font-size:1
|
|
212 |
.sucuriscan_wpconfig_keys_updated textarea{width:100%;height:250px;background:#f5f5f5;font-family:monospace;font-size:12px;resize:vertical;margin:20px 0 0 0}
|
213 |
.sucuriscan-maincontent .sucuriscan-last-logins{margin-top:0}
|
214 |
.sucuriscan-maincontent .sucuriscan-last-logins .sucuriscan-ellipsis{width:150px;line-height:inherit}
|
215 |
-
.sucuriscan-maincontent .sucuriscan-modifiedfiles .sucuriscan-ellipsis{width:100px}
|
216 |
.sucuriscan-maincontent .sucuriscan-full-textarea{width:100%;height:400px;line-height:normal;resize:vertical;padding:10px}
|
217 |
-
.sucuriscan-maincontent .sucuriscan-auditlogs{margin-bottom:0}
|
218 |
-
.sucuriscan-maincontent .sucuriscan-auditlogs td small{font-style:italic}
|
219 |
-
.sucuriscan-maincontent .sucuriscan-auditlogs .sucuriscan-maxper-page{text-align:right}
|
220 |
.sucuriscan-maincontent .sucuriscan-settings{margin-top:0}
|
221 |
.sucuriscan-maincontent .sucuriscan-settings form{display:inline-block}
|
222 |
.sucuriscan-maincontent .sucuriscan-settings select, .sucuriscan-maincontent .sucuriscan-settings .input-text{min-width:220px}
|
146 |
.sucuriscan-scanner-results .sucuriscan-scanner-links tr:nth-child(even){background:#f5f5f5}
|
147 |
.sucuriscan-scanner-results td.sucuriscan-border-bad{border-left-width:4px;border-left-style:solid}
|
148 |
/* Integrity Styles */
|
149 |
+
.sucuriscan-status-type{display:inline-block;width:20px;background:#ddd;text-align:center;text-transform:uppercase;margin-right:10px;padding:0 3px;border:1px solid transparent;border-radius:3px}
|
150 |
.sucuriscan-status-added{background:#dff0d8;color:#3c763d;border-color:#d6e9c6}
|
151 |
.sucuriscan-status-modified{background:#fcf8e3;color:#8a6d3b;border-color:#faebcc}
|
152 |
.sucuriscan-status-removed, td.sucuriscan-corefiles-warning > div{background:#f2dede;color:#a94442;border-color:#ebccd1}
|
154 |
.sucuriscan-maincontent .sucuriscan-integrity-message,
|
155 |
.sucuriscan-maincontent .sucuriscan-wordpress-outdated,
|
156 |
.sucuriscan-maincontent .sucuriscan-auditlogs{margin-top:0;margin-bottom:20px}
|
157 |
+
.sucuriscan-corefiles-abbrs .sucuriscan-status-type{width:initial;font-size:12px;text-transform:capitalize;float:left;margin-top:4px;margin-right:5px}
|
|
|
158 |
.sucuriscan-maincontent td.sucuriscan-corefiles-warning, .sucuriscan-maincontent td.sucuriscan-corefiles-warning p{margin:0;padding:0}
|
159 |
.sucuriscan-maincontent td.sucuriscan-corefiles-warning div{padding:10px;border-width:1px;border-style:solid}
|
160 |
.sucuriscan-maincontent td.sucuriscan-corefiles-warning code{font-size:12px;padding:0 5px}
|
161 |
.sucuriscan-maincontent .sucuriscan-integrity-message{position:relative}
|
162 |
.sucuriscan-maincontent .sucuriscan-integrity-message .sucuriscan-integrity-mark{position:absolute;top:1px;right:1px;background:#7ad03a;font-weight:bold;color:#fff;line-height:35px;padding:0 10px;border-left:1px solid #ddd}
|
163 |
+
.sucuriscan-maincontent .sucuriscan-auditlogs{margin-bottom:0}
|
164 |
+
.sucuriscan-maincontent .sucuriscan-auditlogs td small{font-style:italic}
|
165 |
+
.sucuriscan-maincontent .sucuriscan-auditlogs .sucuriscan-maxper-page{text-align:right}
|
166 |
+
.sucuriscan-maincontent .sucuriscan-ignoredfiles{margin-top:0}
|
167 |
+
.sucuriscan-maincontent .sucuriscan-modifiedfiles .sucuriscan-ellipsis{width:100px}
|
168 |
/* Monitoring Styles */
|
169 |
.sucuriscan-monitoring-settings{margin-bottom:20px}
|
170 |
.sucuriscan-monitoring-settings td.td-with-button{text-align:left}
|
216 |
.sucuriscan_wpconfig_keys_updated textarea{width:100%;height:250px;background:#f5f5f5;font-family:monospace;font-size:12px;resize:vertical;margin:20px 0 0 0}
|
217 |
.sucuriscan-maincontent .sucuriscan-last-logins{margin-top:0}
|
218 |
.sucuriscan-maincontent .sucuriscan-last-logins .sucuriscan-ellipsis{width:150px;line-height:inherit}
|
|
|
219 |
.sucuriscan-maincontent .sucuriscan-full-textarea{width:100%;height:400px;line-height:normal;resize:vertical;padding:10px}
|
|
|
|
|
|
|
220 |
.sucuriscan-maincontent .sucuriscan-settings{margin-top:0}
|
221 |
.sucuriscan-maincontent .sucuriscan-settings form{display:inline-block}
|
222 |
.sucuriscan-maincontent .sucuriscan-settings select, .sucuriscan-maincontent .sucuriscan-settings .input-text{min-width:220px}
|
inc/js/sucuriscan-scripts.js
CHANGED
@@ -50,10 +50,10 @@ jQuery(document).ready(function($){
|
|
50 |
var action = this_button.data('action');
|
51 |
|
52 |
if( action == 'show' ){
|
53 |
-
$('.sucuriscan-corefiles tbody > tr').removeClass('sucuriscan-hidden');
|
54 |
this_button.html('Hide files').data('action', 'hide');
|
55 |
} else {
|
56 |
-
$('.sucuriscan-corefiles tbody > tr').addClass('sucuriscan-hidden');
|
57 |
this_button.html('Show files').data('action', 'show');
|
58 |
}
|
59 |
});
|
50 |
var action = this_button.data('action');
|
51 |
|
52 |
if( action == 'show' ){
|
53 |
+
$('.sucuriscan-corefiles thead tr:last-child, .sucuriscan-corefiles tbody > tr').removeClass('sucuriscan-hidden');
|
54 |
this_button.html('Hide files').data('action', 'hide');
|
55 |
} else {
|
56 |
+
$('.sucuriscan-corefiles thead tr:last-child, .sucuriscan-corefiles tbody > tr').addClass('sucuriscan-hidden');
|
57 |
this_button.html('Show files').data('action', 'show');
|
58 |
}
|
59 |
});
|
inc/tpl/integrity-corefiles.html.tpl
CHANGED
@@ -1,42 +1,82 @@
|
|
1 |
|
2 |
<div class="postbox sucuriscan-border sucuriscan-border-good sucuriscan-integrity-message sucuriscan-%%SUCURI.CoreFiles.GoodVisibility%%">
|
3 |
<span class="sucuriscan-integrity-mark">OK</span>
|
4 |
-
<h3>
|
5 |
|
6 |
<div class="inside">
|
7 |
<p>Your WordPress core files are clean and were not modified.</p>
|
8 |
</div>
|
9 |
</div>
|
10 |
|
11 |
-
<
|
12 |
-
<
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
<span
|
19 |
-
<
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
<p>
|
29 |
-
|
30 |
-
|
31 |
-
<
|
|
|
|
|
32 |
</p>
|
33 |
-
</div>
|
34 |
-
</td>
|
35 |
-
</tr>
|
36 |
-
</thead>
|
37 |
|
38 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
39 |
|
40 |
-
|
41 |
-
</tbody>
|
42 |
-
</table>
|
1 |
|
2 |
<div class="postbox sucuriscan-border sucuriscan-border-good sucuriscan-integrity-message sucuriscan-%%SUCURI.CoreFiles.GoodVisibility%%">
|
3 |
<span class="sucuriscan-integrity-mark">OK</span>
|
4 |
+
<h3>Core integrity</h3>
|
5 |
|
6 |
<div class="inside">
|
7 |
<p>Your WordPress core files are clean and were not modified.</p>
|
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 |
+
|
14 |
+
<table class="wp-list-table widefat sucuriscan-table sucuriscan-corefiles sucuriscan-%%SUCURI.CoreFiles.BadVisibility%%">
|
15 |
+
<thead>
|
16 |
+
<tr>
|
17 |
+
<th colspan="3" class="sucuriscan-clearfix thead-with-button">
|
18 |
+
<span>Core integrity (%%SUCURI.CoreFiles.ListCount%% files)</span>
|
19 |
+
<div class="sucuriscan-pull-right sucuriscan-corefiles-abbrs">
|
20 |
+
<span class="sucuriscan-status-type sucuriscan-status-added">Added</span>
|
21 |
+
<span class="sucuriscan-status-type sucuriscan-status-modified">Modified</span>
|
22 |
+
<span class="sucuriscan-status-type sucuriscan-status-removed">Removed</span>
|
23 |
+
<button id="sucuriscan-corefiles-show" class="button button-primary thead-topright-action" data-action="show">Show files</button>
|
24 |
+
</div>
|
25 |
+
</th>
|
26 |
+
</tr>
|
27 |
+
|
28 |
+
<tr>
|
29 |
+
<td colspan="3" class="sucuriscan-corefiles-warning">
|
30 |
+
<div>
|
31 |
+
<p>
|
32 |
+
Changes in the integrity of your core files were detected. There are files that
|
33 |
+
were added, modified, and/or removed in the core directories
|
34 |
+
<code>/<root></code>, <code>/wp-admin</code> and/or <code>/wp-
|
35 |
+
includes</code>. You may want to check each file to determine if they were
|
36 |
+
infected with malicious code.
|
37 |
+
</p>
|
38 |
+
</div>
|
39 |
+
</td>
|
40 |
+
</tr>
|
41 |
+
|
42 |
+
<tr class="sucuriscan-hidden">
|
43 |
+
<th class="manage-column column-cb check-column">
|
44 |
+
<label class="screen-reader-text" for="cb-select-all-1">Select All</label>
|
45 |
+
<input id="cb-select-all-1" type="checkbox">
|
46 |
+
</th>
|
47 |
+
<th width="70" class="manage-column">Status</th>
|
48 |
+
<th class="manage-column">Filepath</th>
|
49 |
+
</tr>
|
50 |
+
</thead>
|
51 |
+
|
52 |
+
<tbody>
|
53 |
+
%%SUCURI.CoreFiles.List%%
|
54 |
+
</tbody>
|
55 |
+
|
56 |
+
<tfoot>
|
57 |
+
<tr>
|
58 |
+
<td colspan="3">
|
59 |
<p>
|
60 |
+
The action to restore the content of a file will only work with files that were
|
61 |
+
<b>modified</b> or <b>removed</b>, for files that were <b>added</b> you must
|
62 |
+
either remove or mark as fixed. Files marked as <b>fixed</b> will always be
|
63 |
+
ignored from the integrity checks, an attacker can use this option to hide a
|
64 |
+
malicious file, so always check what files are being ignored.
|
65 |
</p>
|
|
|
|
|
|
|
|
|
66 |
|
67 |
+
<label>
|
68 |
+
<select name="sucuriscan_integrity_action">
|
69 |
+
<option value="">Choose action</option>
|
70 |
+
<option value="restore">Restore file(s) content</option>
|
71 |
+
<option value="remove">Remove file(s)</option>
|
72 |
+
<option value="fixed">Mark as fixed</option>
|
73 |
+
</select>
|
74 |
+
</label>
|
75 |
+
|
76 |
+
<button type="submit" class="button button-primary">Send action</button>
|
77 |
+
</td>
|
78 |
+
</tr>
|
79 |
+
</tfoot>
|
80 |
+
</table>
|
81 |
|
82 |
+
</form>
|
|
|
|
inc/tpl/integrity-corefiles.snippet.tpl
CHANGED
@@ -1,9 +1,9 @@
|
|
1 |
|
2 |
<tr class="%%SUCURI.CoreFiles.CssClass%% sucuriscan-hidden">
|
3 |
-
<td>
|
4 |
-
|
5 |
-
|
6 |
-
<div class="sucuriscan-pull-left sucuriscan-monospace">%%SUCURI.CoreFiles.FilePath%%</div>
|
7 |
-
</div>
|
8 |
</td>
|
|
|
|
|
9 |
</tr>
|
1 |
|
2 |
<tr class="%%SUCURI.CoreFiles.CssClass%% sucuriscan-hidden">
|
3 |
+
<td class="check-column">
|
4 |
+
<input type="checkbox" name="sucuriscan_integrity_files[]" value="%%SUCURI.CoreFiles.FilePath%%" />
|
5 |
+
<input type="hidden" name="sucuriscan_integrity_types[]" value="%%SUCURI.CoreFiles.StatusType%%" />
|
|
|
|
|
6 |
</td>
|
7 |
+
<td><span class="sucuriscan-status-type sucuriscan-status-%%SUCURI.CoreFiles.StatusType%%">%%SUCURI.CoreFiles.StatusAbbr%%</span></td>
|
8 |
+
<td><span class="sucuriscan-monospace sucuriscan-wraptext">%%SUCURI.CoreFiles.FilePath%%</span></td>
|
9 |
</tr>
|
inc/tpl/integrity.html.tpl
CHANGED
@@ -1,10 +1,8 @@
|
|
1 |
|
2 |
<div id="poststuff">
|
3 |
-
|
4 |
%%SUCURI.WordpressVersion%%
|
5 |
|
6 |
%%SUCURI.CoreFiles%%
|
7 |
|
8 |
%%SUCURI.AuditLogs%%
|
9 |
-
|
10 |
</div>
|
1 |
|
2 |
<div id="poststuff">
|
|
|
3 |
%%SUCURI.WordpressVersion%%
|
4 |
|
5 |
%%SUCURI.CoreFiles%%
|
6 |
|
7 |
%%SUCURI.AuditLogs%%
|
|
|
8 |
</div>
|
inc/tpl/malwarescan.html.tpl
CHANGED
@@ -4,7 +4,7 @@
|
|
4 |
|
5 |
<p class="description">Visit our <a href="http://sucuri.net/signup?fromloader" target="_blank">coverage & pricing</a> page for details on how sucuri can help you.</p>
|
6 |
|
7 |
-
<form action="%%SUCURI.URL.Scanner%%" method="post"
|
8 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
9 |
<input type="hidden" name="sucuriscan_malware_scan" value="1" />
|
10 |
<button type="submit" class="button button-hero button-primary">Scan Website</button>
|
4 |
|
5 |
<p class="description">Visit our <a href="http://sucuri.net/signup?fromloader" target="_blank">coverage & pricing</a> page for details on how sucuri can help you.</p>
|
6 |
|
7 |
+
<form action="%%SUCURI.URL.Scanner%%" method="post" class="sucuriscan-sitecheck-form">
|
8 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
9 |
<input type="hidden" name="sucuriscan_malware_scan" value="1" />
|
10 |
<button type="submit" class="button button-hero button-primary">Scan Website</button>
|
inc/tpl/setup-notice.html.tpl
CHANGED
@@ -6,8 +6,8 @@
|
|
6 |
|
7 |
<div class="sucuriscan-pull-left">
|
8 |
<p>
|
9 |
-
Plugin not fully activated yet. Please generate the free API<br>
|
10 |
-
|
11 |
</p>
|
12 |
</div>
|
13 |
|
6 |
|
7 |
<div class="sucuriscan-pull-left">
|
8 |
<p>
|
9 |
+
Plugin not fully activated yet. Please generate the free API key to<br>
|
10 |
+
enable audit logging, integrity checking, email alerts and other tools.
|
11 |
</p>
|
12 |
</div>
|
13 |
|
readme.txt
CHANGED
@@ -3,7 +3,7 @@ Contributors: dd@sucuri.net
|
|
3 |
Donate Link: http://sitecheck.sucuri.net
|
4 |
Tags: malware, security, firewall, scan, spam, virus, sucuri, protection
|
5 |
Requires at least:3.2
|
6 |
-
Stable tag:1.6.
|
7 |
Tested up to: 3.9.2
|
8 |
|
9 |
The Sucuri Security - Auditing, SiteCheck Malware Scanner and Hardening is a security plugin enables you to scan your WordPress site using Sucuri SiteCheck for security and malware issues, and also verifies the security integrity of your core files right in your dashboard. It includes audit trails and post-hack security ions to help you reset passwords and secret keys in case it has been already hacked, or infected with malware.
|
@@ -66,6 +66,13 @@ the compromise on your site).
|
|
66 |
|
67 |
== Changelog ==
|
68 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
69 |
= 1.6.6 =
|
70 |
* Internal code cleanup and re-organization.
|
71 |
* More white lists for the integrity checks.
|
3 |
Donate Link: http://sitecheck.sucuri.net
|
4 |
Tags: malware, security, firewall, scan, spam, virus, sucuri, protection
|
5 |
Requires at least:3.2
|
6 |
+
Stable tag:1.6.8
|
7 |
Tested up to: 3.9.2
|
8 |
|
9 |
The Sucuri Security - Auditing, SiteCheck Malware Scanner and Hardening is a security plugin enables you to scan your WordPress site using Sucuri SiteCheck for security and malware issues, and also verifies the security integrity of your core files right in your dashboard. It includes audit trails and post-hack security ions to help you reset passwords and secret keys in case it has been already hacked, or infected with malware.
|
66 |
|
67 |
== Changelog ==
|
68 |
|
69 |
+
= 1.6.8 =
|
70 |
+
* Fixing interface.
|
71 |
+
|
72 |
+
= 1.6.7 =
|
73 |
+
* Added Support for integrity checks on i18n installations.
|
74 |
+
* Fixed the setting change bug.
|
75 |
+
|
76 |
= 1.6.6 =
|
77 |
* Internal code cleanup and re-organization.
|
78 |
* More white lists for the integrity checks.
|
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 Security</a> <em>(Auditing, Malware Scanner and Hardening)</em> plugin enables you to scan your WordPress site using <a href="http://sitecheck.sucuri.net/" target="_blank">Sucuri SiteCheck</a> right in your dashboard. 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.6.
|
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.6.
|
70 |
|
71 |
/**
|
72 |
* The name of the Sucuri plugin main file.
|
@@ -522,25 +522,35 @@ class SucuriScan {
|
|
522 |
* @return string The real ip address of the user in the current request.
|
523 |
*/
|
524 |
public static function get_remote_addr(){
|
525 |
-
$
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
$remote_addr = preg_replace('/[^0-9a-z.,: ]/', '', $_SERVER[$alternative]);
|
539 |
|
540 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
541 |
}
|
542 |
}
|
543 |
|
|
|
|
|
|
|
|
|
544 |
if( $remote_addr == '::1' ){
|
545 |
$remote_addr = '127.0.0.1';
|
546 |
}
|
@@ -564,19 +574,30 @@ class SucuriScan {
|
|
564 |
/**
|
565 |
* Check whether the site is behing the Sucuri CloudProxy network.
|
566 |
*
|
567 |
-
* @
|
|
|
568 |
*/
|
569 |
-
public static function is_behind_cloudproxy(){
|
570 |
-
if( isset($_SERVER['
|
571 |
-
$http_host = preg_replace('/^(.*):[0-9]+/', '$1', $_SERVER['
|
572 |
} else {
|
573 |
$http_host = 'localhost';
|
574 |
}
|
575 |
|
576 |
$host_by_name = gethostbyname($http_host);
|
577 |
$host_by_addr = gethostbyaddr($host_by_name);
|
|
|
578 |
|
579 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
580 |
}
|
581 |
|
582 |
/**
|
@@ -1333,21 +1354,39 @@ class SucuriScanCache extends SucuriScan {
|
|
1333 |
}
|
1334 |
|
1335 |
/**
|
1336 |
-
*
|
|
|
|
|
1337 |
*
|
1338 |
-
* @param string
|
1339 |
-
* @return
|
1340 |
*/
|
1341 |
-
private function
|
1342 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
1343 |
|
1344 |
-
if(
|
1345 |
-
return
|
1346 |
}
|
1347 |
|
1348 |
return FALSE;
|
1349 |
}
|
1350 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1351 |
/**
|
1352 |
* Update the content of the datastore file with the new entries.
|
1353 |
*
|
@@ -1391,11 +1430,11 @@ class SucuriScanCache extends SucuriScan {
|
|
1391 |
|
1392 |
if( !empty($data_lines) ){
|
1393 |
foreach( $data_lines as $line ){
|
1394 |
-
if( preg_match(
|
1395 |
$data_object['info'][$match[1]] = $match[2];
|
1396 |
}
|
1397 |
|
1398 |
-
elseif( preg_match('
|
1399 |
if(
|
1400 |
$this->valid_key_name($match[1])
|
1401 |
&& !array_key_exists($match[1], $data_object)
|
@@ -1483,8 +1522,11 @@ class SucuriScanCache extends SucuriScan {
|
|
1483 |
* @return boolean TRUE if the operation finished successfully, FALSE otherwise.
|
1484 |
*/
|
1485 |
private function handle_key_data( $key='', $data=NULL, $action='', $lifetime=0, $assoc=FALSE ){
|
1486 |
-
if( preg_match('/^(add|set|get|delete)$/', $action) ){
|
1487 |
-
if(
|
|
|
|
|
|
|
1488 |
$finfo = $this->get_datastore_content($assoc);
|
1489 |
|
1490 |
switch( $action ){
|
@@ -1501,6 +1543,18 @@ class SucuriScanCache extends SucuriScan {
|
|
1501 |
return $finfo['entries'][$key];
|
1502 |
}
|
1503 |
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1504 |
case 'delete':
|
1505 |
unset($finfo['entries'][$key]);
|
1506 |
return $this->save_new_entries($finfo);
|
@@ -1551,6 +1605,29 @@ class SucuriScanCache extends SucuriScan {
|
|
1551 |
return $this->handle_key_data( $key, NULL, 'get', $lifetime, $assoc );
|
1552 |
}
|
1553 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1554 |
/**
|
1555 |
* Delete any entry from the datastore file matching the key name specified.
|
1556 |
*
|
@@ -1616,10 +1693,11 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
1616 |
* @param string $option_name Optional parameter with the name of the option that will be filtered.
|
1617 |
* @return array List of options retrieved from the query in the database.
|
1618 |
*/
|
1619 |
-
public function get_options_from_db( $filter_by='', $option_name='' ){
|
1620 |
global $wpdb;
|
1621 |
|
1622 |
$output = FALSE;
|
|
|
1623 |
switch($filter_by){
|
1624 |
case 'all_plugin_options':
|
1625 |
$output = $wpdb->get_results("SELECT * FROM {$wpdb->options} WHERE option_name LIKE 'sucuriscan%' ORDER BY option_id ASC");
|
@@ -3642,8 +3720,8 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
3642 |
$can_cache = class_exists('SucuriScanCache');
|
3643 |
|
3644 |
if( $can_cache ){
|
3645 |
-
$
|
3646 |
-
$cached_data = $
|
3647 |
|
3648 |
// Return the previously cached results of this function.
|
3649 |
if( $cached_data !== FALSE ){
|
@@ -3710,7 +3788,7 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
3710 |
|
3711 |
if( $can_cache ){
|
3712 |
// Add the information of the plugins to the file-based cache.
|
3713 |
-
$
|
3714 |
}
|
3715 |
|
3716 |
return $plugins;
|
@@ -3748,6 +3826,42 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
3748 |
return FALSE;
|
3749 |
}
|
3750 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3751 |
}
|
3752 |
|
3753 |
/**
|
@@ -4520,8 +4634,8 @@ function sucuriscan_scanner_page(){
|
|
4520 |
SucuriScanInterface::check_permissions();
|
4521 |
|
4522 |
// Check if the information is already cached.
|
4523 |
-
$
|
4524 |
-
$scan_results = $
|
4525 |
|
4526 |
if(
|
4527 |
(
|
@@ -4562,11 +4676,11 @@ function sucuriscan_sitecheck_info( $res=array() ){
|
|
4562 |
}
|
4563 |
|
4564 |
else {
|
4565 |
-
$
|
4566 |
$display_results = TRUE;
|
4567 |
|
4568 |
// Cache the scanning results to reduce memory lose.
|
4569 |
-
if( !$
|
4570 |
SucuriScanInterface::error( 'Could not cache the results of the SiteCheck scanning.' );
|
4571 |
}
|
4572 |
}
|
@@ -4787,18 +4901,20 @@ function sucuriscan_sitecheck_info( $res=array() ){
|
|
4787 |
<tr>
|
4788 |
<th colspan="2">Web application details</th>
|
4789 |
</tr>
|
4790 |
-
<?php
|
4791 |
-
<?php
|
4792 |
-
<?php
|
4793 |
-
<?php
|
4794 |
-
|
4795 |
-
<
|
4796 |
-
<
|
4797 |
-
|
4798 |
-
|
4799 |
-
|
4800 |
-
|
4801 |
-
|
|
|
|
|
4802 |
|
4803 |
<?php foreach( $res['SYSTEM']['NOTICE'] as $j=>$notice ): ?>
|
4804 |
<?php if( is_array($notice) ){ $notice = implode(', ', $notice); } ?>
|
@@ -5701,15 +5817,20 @@ function sucuriscan_harden_wpcontent(){
|
|
5701 |
}
|
5702 |
}
|
5703 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5704 |
sucuriscan_harden_status(
|
5705 |
'Restrict wp-content access',
|
5706 |
$cp,
|
5707 |
'sucuriscan_harden_wpcontent',
|
5708 |
'WP-content directory properly hardened',
|
5709 |
'WP-content directory not hardened',
|
5710 |
-
|
5711 |
-
.'issue after this with a theme or plugin in your site, like for example images not displaying, '
|
5712 |
-
.'remove the <code>.htaccess</code> file located at the <code>/wp-content/</code> directory.',
|
5713 |
$upmsg
|
5714 |
);
|
5715 |
}
|
@@ -5816,10 +5937,19 @@ function sucuriscan_harden_phpversion(){
|
|
5816 |
*/
|
5817 |
function sucuriscan_cloudproxy_enabled(){
|
5818 |
$btn_string = '';
|
5819 |
-
$
|
|
|
5820 |
$status = 1;
|
5821 |
|
5822 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5823 |
$status = 0;
|
5824 |
$btn_string = '<a href="http://cloudproxy.sucuri.net/" target="_blank" class="button button-primary">Harden</a>';
|
5825 |
}
|
@@ -5830,9 +5960,7 @@ function sucuriscan_cloudproxy_enabled(){
|
|
5830 |
NULL,
|
5831 |
'Your website is protected by a Website Firewall (WAF)',
|
5832 |
$btn_string . 'Your website is not protected by a Website Firewall (WAF)',
|
5833 |
-
|
5834 |
-
.'SQL injections, etc) and helping it remain malware and blacklist free. This test checks if your site is '
|
5835 |
-
.'using <a href="http://cloudproxy.sucuri.net/" target="_blank">Sucuri\'s CloudProxy WAF</a> to protect your site. ',
|
5836 |
NULL
|
5837 |
);
|
5838 |
}
|
@@ -6062,13 +6190,8 @@ function sucuriscan_harden_dbtables(){
|
|
6062 |
function sucuriscan_page(){
|
6063 |
SucuriScanInterface::check_permissions();
|
6064 |
|
6065 |
-
|
6066 |
-
|
6067 |
-
&& SucuriScanRequest::post(':force_scan')
|
6068 |
-
){
|
6069 |
-
SucuriScanEvent::notify_event( 'plugin_change', 'Filesystem scan forced at: ' . date('r') );
|
6070 |
-
SucuriScanEvent::filesystem_scan(TRUE);
|
6071 |
-
}
|
6072 |
|
6073 |
$template_variables = array(
|
6074 |
'WordpressVersion' => sucuriscan_wordpress_outdated(),
|
@@ -6079,6 +6202,73 @@ function sucuriscan_page(){
|
|
6079 |
echo SucuriScanTemplate::get_template('integrity', $template_variables);
|
6080 |
}
|
6081 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6082 |
/**
|
6083 |
* Retrieve a list of md5sum and last modification time of all the files in the
|
6084 |
* folder specified. This is a recursive function.
|
@@ -6247,9 +6437,12 @@ function sucuriscan_core_files(){
|
|
6247 |
);
|
6248 |
|
6249 |
if( $site_version && SucuriScanOption::get_option(':scan_checksums') == 'enabled' ){
|
6250 |
-
|
|
|
6251 |
|
6252 |
if( $latest_hashes ){
|
|
|
|
|
6253 |
$counter = 0;
|
6254 |
|
6255 |
foreach( $latest_hashes as $list_type => $file_list ){
|
@@ -6261,24 +6454,10 @@ function sucuriscan_core_files(){
|
|
6261 |
}
|
6262 |
|
6263 |
foreach( $file_list as $file_path ){
|
6264 |
-
|
6265 |
-
|
6266 |
-
'%s <a href="%s" target="_blank">%s</a>',
|
6267 |
-
$file_path,
|
6268 |
-
'%%SUCURI.URL.Infosys%%#htaccess-integrity',
|
6269 |
-
'<em>(Check HTAccess Integrity)</em>'
|
6270 |
-
);
|
6271 |
-
}
|
6272 |
-
|
6273 |
-
elseif( $file_path == 'wp-config.php' ){
|
6274 |
-
$file_path = sprintf(
|
6275 |
-
'%s <a href="%s" target="_blank">%s</a>',
|
6276 |
-
$file_path,
|
6277 |
-
'%%SUCURI.URL.Infosys%%#wpconfig-rules',
|
6278 |
-
'<em>(Check WP Config Variables)</em>'
|
6279 |
-
);
|
6280 |
-
}
|
6281 |
|
|
|
6282 |
$css_class = ( $counter % 2 == 0 ) ? '' : 'alternate';
|
6283 |
$template_variables['CoreFiles.List'] .= SucuriScanTemplate::get_snippet('integrity-corefiles', array(
|
6284 |
'CoreFiles.CssClass' => $css_class,
|
@@ -6318,7 +6497,7 @@ function sucuriscan_core_files(){
|
|
6318 |
* @param integer $version Valid version number of the WordPress project.
|
6319 |
* @return array Associative array with these keys: modified, stable, removed, added.
|
6320 |
*/
|
6321 |
-
function
|
6322 |
$latest_hashes = SucuriScanAPI::get_official_checksums($version);
|
6323 |
|
6324 |
if( !$latest_hashes ){ return FALSE; }
|
@@ -6337,32 +6516,32 @@ function sucuriscan_check_wp_integrity( $version=0 ){
|
|
6337 |
$wp_core_hashes = array_merge( $wp_top_hashes, $wp_admin_hashes, $wp_includes_hashes );
|
6338 |
|
6339 |
// Compare remote and local checksums and search removed files.
|
6340 |
-
foreach( $latest_hashes as $
|
6341 |
-
if( sucuriscan_ignore_integrity_filepath($
|
6342 |
|
6343 |
-
$full_filepath = sprintf('%s/%s', ABSPATH, $
|
6344 |
|
6345 |
if( file_exists($full_filepath) ){
|
6346 |
$local_checksum = @md5_file($full_filepath);
|
6347 |
|
6348 |
if( $local_checksum && $local_checksum == $remote_checksum ){
|
6349 |
-
$output['stable'][] = $
|
6350 |
} else {
|
6351 |
-
$output['modified'][] = $
|
6352 |
}
|
6353 |
} else {
|
6354 |
-
$output['removed'][] = $
|
6355 |
}
|
6356 |
}
|
6357 |
|
6358 |
// Search added files (files not common in a normal wordpress installation).
|
6359 |
-
foreach( $wp_core_hashes as $
|
6360 |
-
$
|
6361 |
|
6362 |
-
if( sucuriscan_ignore_integrity_filepath($
|
6363 |
|
6364 |
-
if( !isset($latest_hashes[$
|
6365 |
-
$output['added'][] = $
|
6366 |
}
|
6367 |
}
|
6368 |
|
@@ -6372,10 +6551,12 @@ function sucuriscan_check_wp_integrity( $version=0 ){
|
|
6372 |
/**
|
6373 |
* Ignore irrelevant files and directories from the integrity checking.
|
6374 |
*
|
6375 |
-
* @param string $
|
6376 |
-
* @return boolean
|
6377 |
*/
|
6378 |
-
function sucuriscan_ignore_integrity_filepath( $
|
|
|
|
|
6379 |
// List of files that will be ignored from the integrity checking.
|
6380 |
$ignore_files = array(
|
6381 |
'^sucuri-[0-9a-z]+\.php$',
|
@@ -6391,14 +6572,30 @@ function sucuriscan_ignore_integrity_filepath( $filepath='' ){
|
|
6391 |
'^(503|404)\.php$',
|
6392 |
'^500\.(shtml|php)$',
|
6393 |
'^40[0-9]\.shtml$',
|
6394 |
-
'^([^\/]*)\.(pdf|css)$',
|
6395 |
'^google[0-9a-z]{16}\.html$',
|
6396 |
'^pinterest-[0-9a-z]{5}\.html$',
|
6397 |
'(^|\/)error_log$',
|
6398 |
);
|
6399 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6400 |
foreach( $ignore_files as $ignore_pattern ){
|
6401 |
-
if( preg_match('/'.$ignore_pattern.'/', $
|
6402 |
return TRUE;
|
6403 |
}
|
6404 |
}
|
@@ -7778,7 +7975,9 @@ function sucuriscan_settings_form_submissions( $page_nonce=NULL ){
|
|
7778 |
$options_updated_counter = 0;
|
7779 |
|
7780 |
foreach( $sucuriscan_notify_options as $alert_type => $alert_label ){
|
7781 |
-
|
|
|
|
|
7782 |
$option_value = ( $option_value == '1' ) ? 'enabled' : 'disabled';
|
7783 |
SucuriScanOption::update_option( $alert_type, $option_value );
|
7784 |
$options_updated_counter += 1;
|
4 |
Plugin URI: http://wordpress.sucuri.net/
|
5 |
Description: The <a href="http://sucuri.net/" target="_blank">Sucuri Security</a> <em>(Auditing, Malware Scanner and Hardening)</em> plugin enables you to scan your WordPress site using <a href="http://sitecheck.sucuri.net/" target="_blank">Sucuri SiteCheck</a> right in your dashboard. 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.6.8
|
8 |
Author URI: http://sucuri.net
|
9 |
*/
|
10 |
|
66 |
/**
|
67 |
* Current version of the plugin's code.
|
68 |
*/
|
69 |
+
define('SUCURISCAN_VERSION', '1.6.8');
|
70 |
|
71 |
/**
|
72 |
* The name of the Sucuri plugin main file.
|
522 |
* @return string The real ip address of the user in the current request.
|
523 |
*/
|
524 |
public static function get_remote_addr(){
|
525 |
+
$remote_addr = '';
|
526 |
+
|
527 |
+
if( self::is_behind_cloudproxy() ){
|
528 |
+
$alternatives = array(
|
529 |
+
'HTTP_X_REAL_IP',
|
530 |
+
'HTTP_CLIENT_IP',
|
531 |
+
'HTTP_X_FORWARDED_FOR',
|
532 |
+
'HTTP_X_FORWARDED',
|
533 |
+
'HTTP_FORWARDED_FOR',
|
534 |
+
'HTTP_FORWARDED',
|
535 |
+
'REMOTE_ADDR',
|
536 |
+
'SUCURI_RIP',
|
537 |
+
);
|
|
|
538 |
|
539 |
+
foreach( $alternatives as $alternative ){
|
540 |
+
if(
|
541 |
+
isset($_SERVER[$alternative])
|
542 |
+
&& self::is_valid_ip($_SERVER[$alternative])
|
543 |
+
){
|
544 |
+
$remote_addr = $_SERVER[$alternative];
|
545 |
+
break;
|
546 |
+
}
|
547 |
}
|
548 |
}
|
549 |
|
550 |
+
elseif( isset($_SERVER['REMOTE_ADDR']) ) {
|
551 |
+
$remote_addr = $_SERVER['REMOTE_ADDR'];
|
552 |
+
}
|
553 |
+
|
554 |
if( $remote_addr == '::1' ){
|
555 |
$remote_addr = '127.0.0.1';
|
556 |
}
|
574 |
/**
|
575 |
* Check whether the site is behing the Sucuri CloudProxy network.
|
576 |
*
|
577 |
+
* @param boolean $verbose Return an array with the hostname, address, and status, or not.
|
578 |
+
* @return boolean Either TRUE or FALSE if the site is behind CloudProxy.
|
579 |
*/
|
580 |
+
public static function is_behind_cloudproxy( $verbose=FALSE ){
|
581 |
+
if( isset($_SERVER['SERVER_NAME']) ){
|
582 |
+
$http_host = preg_replace('/^(.*):[0-9]+/', '$1', $_SERVER['SERVER_NAME']);
|
583 |
} else {
|
584 |
$http_host = 'localhost';
|
585 |
}
|
586 |
|
587 |
$host_by_name = gethostbyname($http_host);
|
588 |
$host_by_addr = gethostbyaddr($host_by_name);
|
589 |
+
$status = (bool) preg_match('/^cloudproxy[0-9]+\.sucuri\.net$/', $host_by_addr);
|
590 |
|
591 |
+
if( $verbose ){
|
592 |
+
return array(
|
593 |
+
'http_host' => $http_host,
|
594 |
+
'host_name' => $host_by_name,
|
595 |
+
'host_addr' => $host_by_addr,
|
596 |
+
'status' => $status,
|
597 |
+
);
|
598 |
+
}
|
599 |
+
|
600 |
+
return $status;
|
601 |
}
|
602 |
|
603 |
/**
|
1354 |
}
|
1355 |
|
1356 |
/**
|
1357 |
+
* Define the pattern for the regular expression that will check if a cache key
|
1358 |
+
* is valid or not, and also will help the function that parses the file to see
|
1359 |
+
* which characters of each line are the keys are which are the values.
|
1360 |
*
|
1361 |
+
* @param string $action Either "valid", "content", or "header".
|
1362 |
+
* @return string Cache key pattern.
|
1363 |
*/
|
1364 |
+
private function key_pattern( $action='valid' ){
|
1365 |
+
if( $action == 'valid' ){
|
1366 |
+
return '/^([0-9a-zA-Z_]+)$/';
|
1367 |
+
}
|
1368 |
+
|
1369 |
+
if( $action == 'content' ){
|
1370 |
+
return '/^([0-9a-zA-Z_]+):(.+)/';
|
1371 |
+
}
|
1372 |
|
1373 |
+
if( $action == 'header' ){
|
1374 |
+
return '/^\/\/ ([a-z_]+)=(.*);$/';
|
1375 |
}
|
1376 |
|
1377 |
return FALSE;
|
1378 |
}
|
1379 |
|
1380 |
+
/**
|
1381 |
+
* Check whether a key has a valid name or not.
|
1382 |
+
*
|
1383 |
+
* @param string $key Unique name to identify the data in the datastore file.
|
1384 |
+
* @return boolean TRUE if the format of the key name is valid, FALSE otherwise.
|
1385 |
+
*/
|
1386 |
+
private function valid_key_name( $key='' ){
|
1387 |
+
return (bool) preg_match( $this->key_pattern('valid'), $key );
|
1388 |
+
}
|
1389 |
+
|
1390 |
/**
|
1391 |
* Update the content of the datastore file with the new entries.
|
1392 |
*
|
1430 |
|
1431 |
if( !empty($data_lines) ){
|
1432 |
foreach( $data_lines as $line ){
|
1433 |
+
if( preg_match( $this->key_pattern('header'), $line, $match ) ){
|
1434 |
$data_object['info'][$match[1]] = $match[2];
|
1435 |
}
|
1436 |
|
1437 |
+
elseif( preg_match( $this->key_pattern('content'), $line, $match ) ){
|
1438 |
if(
|
1439 |
$this->valid_key_name($match[1])
|
1440 |
&& !array_key_exists($match[1], $data_object)
|
1522 |
* @return boolean TRUE if the operation finished successfully, FALSE otherwise.
|
1523 |
*/
|
1524 |
private function handle_key_data( $key='', $data=NULL, $action='', $lifetime=0, $assoc=FALSE ){
|
1525 |
+
if( preg_match('/^(add|set|get|get_all|exists|delete)$/', $action) ){
|
1526 |
+
if(
|
1527 |
+
$this->valid_key_name($key)
|
1528 |
+
&& $this->usable_datastore
|
1529 |
+
){
|
1530 |
$finfo = $this->get_datastore_content($assoc);
|
1531 |
|
1532 |
switch( $action ){
|
1543 |
return $finfo['entries'][$key];
|
1544 |
}
|
1545 |
break;
|
1546 |
+
case 'get_all': /* no_break */
|
1547 |
+
if( !$this->data_has_expired($lifetime, $finfo) ) {
|
1548 |
+
return $finfo['entries'];
|
1549 |
+
}
|
1550 |
+
case 'exists':
|
1551 |
+
if(
|
1552 |
+
!$this->data_has_expired($lifetime, $finfo)
|
1553 |
+
&& array_key_exists($key, $finfo['entries'])
|
1554 |
+
){
|
1555 |
+
return TRUE;
|
1556 |
+
}
|
1557 |
+
break;
|
1558 |
case 'delete':
|
1559 |
unset($finfo['entries'][$key]);
|
1560 |
return $this->save_new_entries($finfo);
|
1605 |
return $this->handle_key_data( $key, NULL, 'get', $lifetime, $assoc );
|
1606 |
}
|
1607 |
|
1608 |
+
/**
|
1609 |
+
* Retrieve all the entries found in the datastore file.
|
1610 |
+
*
|
1611 |
+
* @param integer $lifetime Life time of the key in the datastore file.
|
1612 |
+
* @param boolean $assoc When TRUE returned objects will be converted into associative arrays.
|
1613 |
+
* @return string Mixed data stored in the datastore file following the unique key name.
|
1614 |
+
*/
|
1615 |
+
public function get_all( $lifetime=0, $assoc=FALSE ){
|
1616 |
+
$assoc = ( $assoc == 'array' ? TRUE : $assoc );
|
1617 |
+
|
1618 |
+
return $this->handle_key_data( 'temp', NULL, 'get_all', $lifetime, $assoc );
|
1619 |
+
}
|
1620 |
+
|
1621 |
+
/**
|
1622 |
+
* Check whether a specific key exists in the datastore file.
|
1623 |
+
*
|
1624 |
+
* @param string $key Unique name to identify the data in the datastore file.
|
1625 |
+
* @return boolean TRUE if the key exists in the datastore file, FALSE otherwise.
|
1626 |
+
*/
|
1627 |
+
public function exists( $key='' ){
|
1628 |
+
return $this->handle_key_data( $key, NULL, 'exists' );
|
1629 |
+
}
|
1630 |
+
|
1631 |
/**
|
1632 |
* Delete any entry from the datastore file matching the key name specified.
|
1633 |
*
|
1693 |
* @param string $option_name Optional parameter with the name of the option that will be filtered.
|
1694 |
* @return array List of options retrieved from the query in the database.
|
1695 |
*/
|
1696 |
+
public static function get_options_from_db( $filter_by='', $option_name='' ){
|
1697 |
global $wpdb;
|
1698 |
|
1699 |
$output = FALSE;
|
1700 |
+
|
1701 |
switch($filter_by){
|
1702 |
case 'all_plugin_options':
|
1703 |
$output = $wpdb->get_results("SELECT * FROM {$wpdb->options} WHERE option_name LIKE 'sucuriscan%' ORDER BY option_id ASC");
|
3720 |
$can_cache = class_exists('SucuriScanCache');
|
3721 |
|
3722 |
if( $can_cache ){
|
3723 |
+
$cache = new SucuriScanCache('plugindata');
|
3724 |
+
$cached_data = $cache->get( 'plugins', SUCURISCAN_GET_PLUGINS_LIFETIME, 'array' );
|
3725 |
|
3726 |
// Return the previously cached results of this function.
|
3727 |
if( $cached_data !== FALSE ){
|
3788 |
|
3789 |
if( $can_cache ){
|
3790 |
// Add the information of the plugins to the file-based cache.
|
3791 |
+
$cache->add( 'plugins', $plugins );
|
3792 |
}
|
3793 |
|
3794 |
return $plugins;
|
3826 |
return FALSE;
|
3827 |
}
|
3828 |
|
3829 |
+
/**
|
3830 |
+
* Retrieve a specific file from the official WordPress subversion repository,
|
3831 |
+
* the content of the file is determined by the tags defined using the site
|
3832 |
+
* version specified. Only official core files are allowed to fetch.
|
3833 |
+
*
|
3834 |
+
* @see http://core.svn.wordpress.org/
|
3835 |
+
* @see http://i18n.svn.wordpress.org/
|
3836 |
+
* @see http://core.svn.wordpress.org/tags/VERSION_NUMBER/
|
3837 |
+
*
|
3838 |
+
* @param string $filepath Relative file path of a project core file.
|
3839 |
+
* @param string $version Optional site version, default will be the global version number.
|
3840 |
+
* @return string Full content of the official file retrieved, FALSE if the file was not found.
|
3841 |
+
*/
|
3842 |
+
public static function get_original_core_file( $filepath='', $version=0 ){
|
3843 |
+
if( !empty($filepath) ){
|
3844 |
+
if( $version == 0 ){
|
3845 |
+
$version = self::site_version();
|
3846 |
+
}
|
3847 |
+
|
3848 |
+
$url = sprintf( 'http://core.svn.wordpress.org/tags/%s/%s', $version, $filepath );
|
3849 |
+
$response = self::api_call( $url, 'GET' );
|
3850 |
+
|
3851 |
+
if( $response ){
|
3852 |
+
if(
|
3853 |
+
isset($response['headers']['content-length'])
|
3854 |
+
&& $response['headers']['content-length'] > 0
|
3855 |
+
&& is_string($response['body'])
|
3856 |
+
){
|
3857 |
+
return $response['body'];
|
3858 |
+
}
|
3859 |
+
}
|
3860 |
+
}
|
3861 |
+
|
3862 |
+
return FALSE;
|
3863 |
+
}
|
3864 |
+
|
3865 |
}
|
3866 |
|
3867 |
/**
|
4634 |
SucuriScanInterface::check_permissions();
|
4635 |
|
4636 |
// Check if the information is already cached.
|
4637 |
+
$cache = new SucuriScanCache('sitecheck');
|
4638 |
+
$scan_results = $cache->get( 'scan_results', SUCURISCAN_SITECHECK_LIFETIME, 'array' );
|
4639 |
|
4640 |
if(
|
4641 |
(
|
4676 |
}
|
4677 |
|
4678 |
else {
|
4679 |
+
$cache = new SucuriScanCache('sitecheck');
|
4680 |
$display_results = TRUE;
|
4681 |
|
4682 |
// Cache the scanning results to reduce memory lose.
|
4683 |
+
if( !$cache->add( 'scan_results', $res ) ){
|
4684 |
SucuriScanInterface::error( 'Could not cache the results of the SiteCheck scanning.' );
|
4685 |
}
|
4686 |
}
|
4901 |
<tr>
|
4902 |
<th colspan="2">Web application details</th>
|
4903 |
</tr>
|
4904 |
+
<?php if( isset($res['WEBAPP']) ): ?>
|
4905 |
+
<?php foreach( $res['WEBAPP'] as $webapp_key=>$webapp_details ): ?>
|
4906 |
+
<?php if( is_array($webapp_details) ): ?>
|
4907 |
+
<?php foreach( $webapp_details as $i=>$details ): ?>
|
4908 |
+
<?php if( is_array($details) ){ $details = isset($details[0]) ? $details[0] : ''; } ?>
|
4909 |
+
<tr>
|
4910 |
+
<td colspan="2">
|
4911 |
+
<span class="sucuriscan-monospace"><?php _e($details) ?></span>
|
4912 |
+
</td>
|
4913 |
+
</tr>
|
4914 |
+
<?php endforeach; ?>
|
4915 |
+
<?php endif; ?>
|
4916 |
+
<?php endforeach; ?>
|
4917 |
+
<?php endif; ?>
|
4918 |
|
4919 |
<?php foreach( $res['SYSTEM']['NOTICE'] as $j=>$notice ): ?>
|
4920 |
<?php if( is_array($notice) ){ $notice = implode(', ', $notice); } ?>
|
5817 |
}
|
5818 |
}
|
5819 |
|
5820 |
+
$description = 'This option blocks direct PHP access to any file inside wp-content. If you experience '
|
5821 |
+
. 'any issue after this with a theme or plugin in your site, like for example images not displaying, '
|
5822 |
+
. 'remove the <code>.htaccess</code> file located at the <code>/wp-content/</code> directory.'
|
5823 |
+
. '</p><p><b>Note:</b> Many <em>(insecure)</em> themes and plugins use a PHP file in this directory '
|
5824 |
+
. 'to generate images like thumbnails and captcha codes, this is intentional so it is recommended '
|
5825 |
+
. 'to check your site once this option is enabled.';
|
5826 |
+
|
5827 |
sucuriscan_harden_status(
|
5828 |
'Restrict wp-content access',
|
5829 |
$cp,
|
5830 |
'sucuriscan_harden_wpcontent',
|
5831 |
'WP-content directory properly hardened',
|
5832 |
'WP-content directory not hardened',
|
5833 |
+
$description,
|
|
|
|
|
5834 |
$upmsg
|
5835 |
);
|
5836 |
}
|
5937 |
*/
|
5938 |
function sucuriscan_cloudproxy_enabled(){
|
5939 |
$btn_string = '';
|
5940 |
+
$verbosity = TRUE;
|
5941 |
+
$proxy_info = SucuriScan::is_behind_cloudproxy($verbosity);
|
5942 |
$status = 1;
|
5943 |
|
5944 |
+
$description = 'A WAF is a protection layer for your web site, blocking all sort of attacks (brute force attempts, '
|
5945 |
+
. 'DDoS, SQL injections, etc) and helping it remain malware and blacklist free. This test checks if your site is '
|
5946 |
+
. 'using <a href="http://cloudproxy.sucuri.net/" target="_blank">Sucuri\'s CloudProxy WAF</a> to protect your site. '
|
5947 |
+
. '</p><p>'
|
5948 |
+
. '<b>HTTP Host:</b> <span class="sucuriscan-monospace">' . $proxy_info['http_host'] . '</span><br>'
|
5949 |
+
. '<b>Host Name:</b> <span class="sucuriscan-monospace">' . $proxy_info['host_name'] . '</span><br>'
|
5950 |
+
. '<b>Host Address:</b> <span class="sucuriscan-monospace">' . $proxy_info['host_addr'] . '</span>';
|
5951 |
+
|
5952 |
+
if( $proxy_info['status'] === FALSE ){
|
5953 |
$status = 0;
|
5954 |
$btn_string = '<a href="http://cloudproxy.sucuri.net/" target="_blank" class="button button-primary">Harden</a>';
|
5955 |
}
|
5960 |
NULL,
|
5961 |
'Your website is protected by a Website Firewall (WAF)',
|
5962 |
$btn_string . 'Your website is not protected by a Website Firewall (WAF)',
|
5963 |
+
$description,
|
|
|
|
|
5964 |
NULL
|
5965 |
);
|
5966 |
}
|
6190 |
function sucuriscan_page(){
|
6191 |
SucuriScanInterface::check_permissions();
|
6192 |
|
6193 |
+
// Process all form submissions.
|
6194 |
+
sucuriscan_integrity_form_submissions();
|
|
|
|
|
|
|
|
|
|
|
6195 |
|
6196 |
$template_variables = array(
|
6197 |
'WordpressVersion' => sucuriscan_wordpress_outdated(),
|
6202 |
echo SucuriScanTemplate::get_template('integrity', $template_variables);
|
6203 |
}
|
6204 |
|
6205 |
+
/**
|
6206 |
+
* Process the requests sent by the form submissions originated in the integrity
|
6207 |
+
* page, all forms must have a nonce field that will be checked against the one
|
6208 |
+
* generated in the template render function.
|
6209 |
+
*
|
6210 |
+
* @return void
|
6211 |
+
*/
|
6212 |
+
function sucuriscan_integrity_form_submissions(){
|
6213 |
+
if( SucuriScanInterface::check_nonce() ){
|
6214 |
+
|
6215 |
+
// Force the execution of the filesystem scanner.
|
6216 |
+
if( SucuriScanRequest::post(':force_scan') ){
|
6217 |
+
SucuriScanEvent::notify_event( 'plugin_change', 'Filesystem scan forced at: ' . date('r') );
|
6218 |
+
SucuriScanEvent::filesystem_scan(TRUE);
|
6219 |
+
}
|
6220 |
+
|
6221 |
+
// Restore, Remove, Mark as fixed the core files.
|
6222 |
+
$allowed_actions = '(restore|remove|fixed)';
|
6223 |
+
$integrity_action = SucuriScanRequest::post(':integrity_action', $allowed_actions);
|
6224 |
+
|
6225 |
+
if( $integrity_action !== FALSE ){
|
6226 |
+
$cache = new SucuriScanCache('integrity');
|
6227 |
+
$integrity_files = SucuriScanRequest::post(':integrity_files', '_array');
|
6228 |
+
$integrity_types = SucuriScanRequest::post(':integrity_types', '_array');
|
6229 |
+
$files_selected = count($integrity_files);
|
6230 |
+
$files_processed = 0;
|
6231 |
+
|
6232 |
+
foreach( $integrity_files as $i => $file_path ){
|
6233 |
+
$full_path = ABSPATH . $file_path;
|
6234 |
+
$status_type = $integrity_types[$i];
|
6235 |
+
|
6236 |
+
switch( $integrity_action ){
|
6237 |
+
case 'restore':
|
6238 |
+
$file_content = SucuriScanAPI::get_original_core_file($file_path);
|
6239 |
+
if( $file_content ){
|
6240 |
+
$restored = @file_put_contents( $full_path, $file_content, LOCK_EX );
|
6241 |
+
$files_processed += ( $restored ? 1 : 0 );
|
6242 |
+
}
|
6243 |
+
break;
|
6244 |
+
case 'remove':
|
6245 |
+
if( @unlink($full_path) ){
|
6246 |
+
$files_processed += 1;
|
6247 |
+
}
|
6248 |
+
break;
|
6249 |
+
case 'fixed':
|
6250 |
+
$cache_key = md5($file_path);
|
6251 |
+
$cache_value = array(
|
6252 |
+
'file_path' => $file_path,
|
6253 |
+
'file_status' => $status_type,
|
6254 |
+
'ignored_at' => time(),
|
6255 |
+
);
|
6256 |
+
$cached = $cache->add( $cache_key, $cache_value );
|
6257 |
+
$files_processed += ( $cached ? 1 : 0 );
|
6258 |
+
break;
|
6259 |
+
}
|
6260 |
+
}
|
6261 |
+
|
6262 |
+
SucuriScanInterface::info(sprintf(
|
6263 |
+
'<code>%d</code> out of <code>%d</code> files were successfully processed.',
|
6264 |
+
$files_selected,
|
6265 |
+
$files_processed
|
6266 |
+
));
|
6267 |
+
}
|
6268 |
+
|
6269 |
+
}
|
6270 |
+
}
|
6271 |
+
|
6272 |
/**
|
6273 |
* Retrieve a list of md5sum and last modification time of all the files in the
|
6274 |
* folder specified. This is a recursive function.
|
6437 |
);
|
6438 |
|
6439 |
if( $site_version && SucuriScanOption::get_option(':scan_checksums') == 'enabled' ){
|
6440 |
+
// Check if there are added, removed, or modified files.
|
6441 |
+
$latest_hashes = sucuriscan_check_core_integrity($site_version);
|
6442 |
|
6443 |
if( $latest_hashes ){
|
6444 |
+
$cache = new SucuriScanCache('integrity');
|
6445 |
+
$ignored_files = $cache->get_all();
|
6446 |
$counter = 0;
|
6447 |
|
6448 |
foreach( $latest_hashes as $list_type => $file_list ){
|
6454 |
}
|
6455 |
|
6456 |
foreach( $file_list as $file_path ){
|
6457 |
+
// Skip files that were marked as fixed.
|
6458 |
+
if( array_key_exists(md5($file_path), $ignored_files) ){ continue; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6459 |
|
6460 |
+
// Generate the HTML code from the snippet template for this file.
|
6461 |
$css_class = ( $counter % 2 == 0 ) ? '' : 'alternate';
|
6462 |
$template_variables['CoreFiles.List'] .= SucuriScanTemplate::get_snippet('integrity-corefiles', array(
|
6463 |
'CoreFiles.CssClass' => $css_class,
|
6497 |
* @param integer $version Valid version number of the WordPress project.
|
6498 |
* @return array Associative array with these keys: modified, stable, removed, added.
|
6499 |
*/
|
6500 |
+
function sucuriscan_check_core_integrity( $version=0 ){
|
6501 |
$latest_hashes = SucuriScanAPI::get_official_checksums($version);
|
6502 |
|
6503 |
if( !$latest_hashes ){ return FALSE; }
|
6516 |
$wp_core_hashes = array_merge( $wp_top_hashes, $wp_admin_hashes, $wp_includes_hashes );
|
6517 |
|
6518 |
// Compare remote and local checksums and search removed files.
|
6519 |
+
foreach( $latest_hashes as $file_path => $remote_checksum ){
|
6520 |
+
if( sucuriscan_ignore_integrity_filepath($file_path) ){ continue; }
|
6521 |
|
6522 |
+
$full_filepath = sprintf('%s/%s', ABSPATH, $file_path);
|
6523 |
|
6524 |
if( file_exists($full_filepath) ){
|
6525 |
$local_checksum = @md5_file($full_filepath);
|
6526 |
|
6527 |
if( $local_checksum && $local_checksum == $remote_checksum ){
|
6528 |
+
$output['stable'][] = $file_path;
|
6529 |
} else {
|
6530 |
+
$output['modified'][] = $file_path;
|
6531 |
}
|
6532 |
} else {
|
6533 |
+
$output['removed'][] = $file_path;
|
6534 |
}
|
6535 |
}
|
6536 |
|
6537 |
// Search added files (files not common in a normal wordpress installation).
|
6538 |
+
foreach( $wp_core_hashes as $file_path => $extra_info ){
|
6539 |
+
$file_path = preg_replace('/^\.\/(.*)/', '$1', $file_path);
|
6540 |
|
6541 |
+
if( sucuriscan_ignore_integrity_filepath($file_path) ){ continue; }
|
6542 |
|
6543 |
+
if( !isset($latest_hashes[$file_path]) ){
|
6544 |
+
$output['added'][] = $file_path;
|
6545 |
}
|
6546 |
}
|
6547 |
|
6551 |
/**
|
6552 |
* Ignore irrelevant files and directories from the integrity checking.
|
6553 |
*
|
6554 |
+
* @param string $file_path File path that will be compared.
|
6555 |
+
* @return boolean TRUE if the file should be ignored, FALSE otherwise.
|
6556 |
*/
|
6557 |
+
function sucuriscan_ignore_integrity_filepath( $file_path='' ){
|
6558 |
+
global $wp_local_package;
|
6559 |
+
|
6560 |
// List of files that will be ignored from the integrity checking.
|
6561 |
$ignore_files = array(
|
6562 |
'^sucuri-[0-9a-z]+\.php$',
|
6572 |
'^(503|404)\.php$',
|
6573 |
'^500\.(shtml|php)$',
|
6574 |
'^40[0-9]\.shtml$',
|
6575 |
+
'^([^\/]*)\.(pdf|css|txt)$',
|
6576 |
'^google[0-9a-z]{16}\.html$',
|
6577 |
'^pinterest-[0-9a-z]{5}\.html$',
|
6578 |
'(^|\/)error_log$',
|
6579 |
);
|
6580 |
|
6581 |
+
/**
|
6582 |
+
* Ignore i18n files.
|
6583 |
+
*
|
6584 |
+
* Sites with i18n have differences compared with the official English version
|
6585 |
+
* of the project, basically they have files with new variables specifying the
|
6586 |
+
* language that will be used in the admin panel, site options, and emails.
|
6587 |
+
*/
|
6588 |
+
if(
|
6589 |
+
isset($wp_local_package)
|
6590 |
+
&& $wp_local_package != 'en_US'
|
6591 |
+
){
|
6592 |
+
$ignore_files[] = 'wp-includes\/version\.php';
|
6593 |
+
$ignore_files[] = 'wp-config-sample\.php';
|
6594 |
+
}
|
6595 |
+
|
6596 |
+
// Determine whether a file must be ignored from the integrity checks or not.
|
6597 |
foreach( $ignore_files as $ignore_pattern ){
|
6598 |
+
if( preg_match('/'.$ignore_pattern.'/', $file_path) ){
|
6599 |
return TRUE;
|
6600 |
}
|
6601 |
}
|
7975 |
$options_updated_counter = 0;
|
7976 |
|
7977 |
foreach( $sucuriscan_notify_options as $alert_type => $alert_label ){
|
7978 |
+
$option_value = SucuriScanRequest::post($alert_type, '(1|0)');
|
7979 |
+
|
7980 |
+
if( $option_value !== FALSE ){
|
7981 |
$option_value = ( $option_value == '1' ) ? 'enabled' : 'disabled';
|
7982 |
SucuriScanOption::update_option( $alert_type, $option_value );
|
7983 |
$options_updated_counter += 1;
|