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

Version Description

Download this release

Release Info

Developer akresic
Plugin Icon 128x128 Sucuri Security – Auditing, Malware Scanner and Security Hardening
Version 1.7.7
Comparing to
See all releases

Code changes from version 1.7.6 to 1.7.7

inc/css/sucuriscan-default-css.css CHANGED
@@ -1,6 +1,6 @@
1
  /**
2
  * Sucuri Security - SiteCheck Malware Scanner
3
- * Copyright (C) 2010-2014 Sucuri Security - http://sucuri.net
4
  * Released under the GPL - see LICENSE file for details.
5
  */
6
  /* Generic Styles */
@@ -98,13 +98,19 @@
98
  .sucuriscan-maincontent .thead-with-button select{margin:0;padding:0}
99
  .sucuriscan-maincontent .thead-topright-action{display:inline-block;float:right}
100
  /* Sidebar Styles */
101
- .sucuriscan-sidebar .sucuriscan-ad{border:1px solid #ccc;margin:0 0 20px 0;padding:20px;border-radius:4px}
102
- .sucuriscan-sidebar .sucuriscan-ad h2{font-size:18px;line-height:normal;padding:0}
103
- .sucuriscan-sidebar .sucuriscan-ad p:last-child{margin-bottom:0}
104
- .sucuriscan-sidebar .sucuriscan-ad .sucuriscan-list li{margin-left:17px}
105
- .sucuriscan-sidebar .sucuriscan-ad:nth-child(odd){background-color:#bbe8f5;border-color:#4393ac}
106
- .sucuriscan-sidebar .sucuriscan-ad:nth-child(even){background-color:#ececec;border-color:#999}
 
 
 
 
 
107
  .sucuriscan-scanner-video{width:100%;background:#fff;border:1px solid #ddd}
 
108
  /* WordPress Alerts */
109
  div.sucuriscan-alert{position:relative;margin:0 0 20px 0}
110
  div.sucuriscan-alert > a.close{position:absolute;top:10px;right:10px;font-size:18px;font-weight:bold;text-decoration:none}
@@ -172,7 +178,17 @@ div.sucuriscan-alert > a.close{position:absolute;top:10px;right:10px;font-size:1
172
  .sucuriscan-auditlogs .sucuriscan-auditlog-notice{background:#428bca}
173
  .sucuriscan-auditlogs .sucuriscan-auditlog-warning, .sucuriscan-label-modified{background:#f0ad4e}
174
  .sucuriscan-auditlogs .sucuriscan-auditlog-error, .sucuriscan-label-removed{background:#f27d7d}
175
- .sucuriscan-auditlogs .sucuriscan-auditlog-critical{background:#000}
 
 
 
 
 
 
 
 
 
 
176
  /* Audit Report Styles */
177
  .sucuriscan-maincontent .sucuriscan-audit-report{border-left-width:1px}
178
  .sucuriscan-audit-report .sucuriscan-report-row{margin-bottom:10px}
1
  /**
2
  * Sucuri Security - SiteCheck Malware Scanner
3
+ * Copyright (C) 2010-2015 Sucuri Security - http://sucuri.net
4
  * Released under the GPL - see LICENSE file for details.
5
  */
6
  /* Generic Styles */
98
  .sucuriscan-maincontent .thead-with-button select{margin:0;padding:0}
99
  .sucuriscan-maincontent .thead-topright-action{display:inline-block;float:right}
100
  /* Sidebar Styles */
101
+ .sucuriscan-sidebar .sucuriscan-ad{margin-bottom:20px}
102
+ .sucuriscan-sidebar .sucuriscan-ad-content{padding:1.5em;padding-bottom:0.5em;border:1px solid #ccc;border-bottom:0;border-radius:3px 3px 0 0}
103
+ .sucuriscan-sidebar .sucuriscan-ad:nth-child(odd) .sucuriscan-ad-content{background-color:#bbe8f5;border-color:#4393ac}
104
+ .sucuriscan-sidebar .sucuriscan-ad:nth-child(even) .sucuriscan-ad-content{background-color:#ececec;border-color:#999}
105
+ .sucuriscan-sidebar .sucuriscan-ad-content h2{font-size:18px;line-height:normal;padding:0}
106
+ .sucuriscan-sidebar .sucuriscan-ad-content .sucuriscan-list li{margin-left:17px}
107
+ .sucuriscan-sidebar .sucuriscan-ad-footer{margin-bottom:0}
108
+ .sucuriscan-sidebar .sucuriscan-ad-footer .button{width:50%;height:initial;text-align:center;line-height:36px}
109
+ .sucuriscan-sidebar .sucuriscan-ad-footer .button:first-child{border-right:0}
110
+ .sucuriscan-sidebar .sucuriscan-ad-footer .button.sucuriscan-pull-left{border-radius:0 0 0 3px}
111
+ .sucuriscan-sidebar .sucuriscan-ad-footer .button.sucuriscan-pull-right{border-radius:0 0 3px 0}
112
  .sucuriscan-scanner-video{width:100%;background:#fff;border:1px solid #ddd}
113
+ .sucuriscan-sidebar .sucuriscan-supportbtn{width:100%;height:initial;text-align:center;line-height:36px;margin-top:15px;padding:0}
114
  /* WordPress Alerts */
115
  div.sucuriscan-alert{position:relative;margin:0 0 20px 0}
116
  div.sucuriscan-alert > a.close{position:absolute;top:10px;right:10px;font-size:18px;font-weight:bold;text-decoration:none}
178
  .sucuriscan-auditlogs .sucuriscan-auditlog-notice{background:#428bca}
179
  .sucuriscan-auditlogs .sucuriscan-auditlog-warning, .sucuriscan-label-modified{background:#f0ad4e}
180
  .sucuriscan-auditlogs .sucuriscan-auditlog-error, .sucuriscan-label-removed{background:#f27d7d}
181
+ .sucuriscan-auditlogs .sucuriscan-auditlog-critical{background:#000000}
182
+ .sucuriscan-auditlogs tbody tr:hover .sucuriscan-tooltip{display:block}
183
+ .sucuriscan-auditlogs .sucuriscan-tooltip{display:none;position:absolute;width:initial;margin:-17px 0px 0px 62px}
184
+ .sucuriscan-auditlogs .sucuriscan-tooltip:before{content:' ';position:absolute;top:5px;left:-5px;border:4px solid #000;border-left:none;border-right-width:5px;border-top-color:transparent;border-bottom-color:transparent}
185
+ .sucuriscan-auditlogs .sucuriscan-severity .sucuriscan-auditlog-success:before{border-right-color:#5cb85c}
186
+ .sucuriscan-auditlogs .sucuriscan-severity .sucuriscan-auditlog-debug:before{border-right-color:#c690ec}
187
+ .sucuriscan-auditlogs .sucuriscan-severity .sucuriscan-auditlog-info:before{border-right-color:#5bc0de}
188
+ .sucuriscan-auditlogs .sucuriscan-severity .sucuriscan-auditlog-notice:before{border-right-color:#428bca}
189
+ .sucuriscan-auditlogs .sucuriscan-severity .sucuriscan-auditlog-warning:before{border-right-color:#f0ad4e}
190
+ .sucuriscan-auditlogs .sucuriscan-severity .sucuriscan-auditlog-error:before{border-right-color:#f27d7d}
191
+ .sucuriscan-auditlogs .sucuriscan-severity .sucuriscan-auditlog-critical:before{border-right-color:#000000}
192
  /* Audit Report Styles */
193
  .sucuriscan-maincontent .sucuriscan-audit-report{border-left-width:1px}
194
  .sucuriscan-audit-report .sucuriscan-report-row{margin-bottom:10px}
inc/js/sucuriscan-scripts.js CHANGED
@@ -1,6 +1,6 @@
1
  /**
2
  * Sucuri Security - SiteCheck Malware Scanner
3
- * Copyright (C) 2010-2014 Sucuri Security - http://sucuri.net
4
  * Released under the GPL - see LICENSE file for details.
5
  */
6
 
1
  /**
2
  * Sucuri Security - SiteCheck Malware Scanner
3
+ * Copyright (C) 2010-2015 Sucuri Security - http://sucuri.net
4
  * Released under the GPL - see LICENSE file for details.
5
  */
6
 
inc/tpl/base.html.tpl CHANGED
@@ -28,28 +28,45 @@
28
  <div class="sucuriscan-sidebar sucuriscan-%%SUCURI.AdsVisibility%%">
29
 
30
  <div class="sucuriscan-ad">
31
- <h2>Is your website infected with malware? Blacklisted by Google?</h2>
32
- <p>Don't know where to start? Get cleared today by <a href="http://sucuri.net/signup" target="_blank">Sucuri Security</a>!</p>
33
- <p><a href="http://sucuri.net/tour" target="_blank" class="button-primary">Read more</a></p>
 
 
 
 
 
 
 
 
34
  </div>
35
 
36
  <div class="sucuriscan-ad">
37
- <h2>Preventive website security in the cloud!</h2>
38
- <ul class="sucuriscan-list">
39
- <li>Web Application Firewall (WAF) Protection</li>
40
- <li>Virtual Website Patching</li>
41
- <li>Cloud Intrusion Prevention System (IPS)</li>
42
- <li>High Security Website Monitoring</li>
43
- <li>Malicious Traffic Filtering</li>
44
- </ul>
45
- <p>
46
- <a href="http://cloudproxy.sucuri.net/signup" target="_blank" class="button button-primary">Sign up now</a>
47
- <a href="http://cloudproxy.sucuri.net/" target="_blank" class="button button-primary">Read more</a>
48
- </p>
 
 
 
 
 
 
49
  </div>
50
 
51
  <iframe src="https://www.youtube-nocookie.com/embed/EVa9FY3nKuQ" height="250" class="sucuriscan-scanner-video" allowfullscreen></iframe>
52
 
 
 
 
53
  </div>
54
 
55
  </div>
28
  <div class="sucuriscan-sidebar sucuriscan-%%SUCURI.AdsVisibility%%">
29
 
30
  <div class="sucuriscan-ad">
31
+ <div class="sucuriscan-ad-content">
32
+ <h2>Is your website infected with malware? Blacklisted by Google?</h2>
33
+ <p>Don't know where to start? Get cleared today by <a href="http://sucuri.net/signup" target="_blank">Sucuri Security</a>!</p>
34
+ </div>
35
+
36
+ <div class="sucuriscan-ad-footer sucuriscan-clearfix">
37
+ <a href="http://sucuri.net/website-antivirus/signup" target="_blank"
38
+ class="button button-primary sucuriscan-pull-left">Sign up now</a>
39
+ <a href="http://sucuri.net/website-antivirus/" target="_blank"
40
+ class="button button-primary sucuriscan-pull-right">Read more</a>
41
+ </div>
42
  </div>
43
 
44
  <div class="sucuriscan-ad">
45
+ <div class="sucuriscan-ad-content">
46
+ <h2>Preventive website security in the cloud!</h2>
47
+
48
+ <ul class="sucuriscan-list">
49
+ <li>Web Application Firewall (WAF) Protection</li>
50
+ <li>Virtual Website Patching</li>
51
+ <li>Cloud Intrusion Prevention System (IPS)</li>
52
+ <li>High Security Website Monitoring</li>
53
+ <li>Malicious Traffic Filtering</li>
54
+ </ul>
55
+ </div>
56
+
57
+ <div class="sucuriscan-ad-footer sucuriscan-clearfix">
58
+ <a href="http://sucuri.net/website-firewall/signup" target="_blank"
59
+ class="button button-primary sucuriscan-pull-left">Sign up now</a>
60
+ <a href="http://sucuri.net/website-firewall/" target="_blank"
61
+ class="button button-primary sucuriscan-pull-right">Read more</a>
62
+ </div>
63
  </div>
64
 
65
  <iframe src="https://www.youtube-nocookie.com/embed/EVa9FY3nKuQ" height="250" class="sucuriscan-scanner-video" allowfullscreen></iframe>
66
 
67
+ <a href="https://wordpress.org/support/plugin/sucuri-scanner" target="_blank"
68
+ class="button button-primary sucuriscan-supportbtn">Visit Support Forum</a>
69
+
70
  </div>
71
 
72
  </div>
inc/tpl/integrity-auditlogs.html.tpl CHANGED
@@ -2,8 +2,17 @@
2
  <table class="wp-list-table widefat sucuriscan-table sucuriscan-table-double-title sucuriscan-auditlogs">
3
  <thead>
4
  <tr>
5
- <th colspan="4">Audit Logs (%%SUCURI.AuditLogs.Count%% latest logs)</th>
 
 
 
 
 
 
 
 
6
  </tr>
 
7
  <tr>
8
  <th>&nbsp;</th>
9
  <th>Username</th>
2
  <table class="wp-list-table widefat sucuriscan-table sucuriscan-table-double-title sucuriscan-auditlogs">
3
  <thead>
4
  <tr>
5
+ <th colspan="4" class="thead-with-button">
6
+ <span>Audit Logs (%%SUCURI.AuditLogs.Count%% latest logs)</span>
7
+ <form action="%%SUCURI.URL.Settings%%" method="post"
8
+ class="thead-topright-action sucuriscan-%%SUCURI.AuditLogs.EnableAuditReportVisibility%%">
9
+ <input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
10
+ <input type="hidden" name="sucuriscan_audit_report" value="enable" />
11
+ <button type="submit" class="button-primary">Enable Audit Report</button>
12
+ </form>
13
+ </th>
14
  </tr>
15
+
16
  <tr>
17
  <th>&nbsp;</th>
18
  <th>Username</th>
inc/tpl/integrity-auditlogs.snippet.tpl CHANGED
@@ -1,9 +1,10 @@
1
 
2
  <tr class="%%SUCURI.AuditLog.CssClass%%">
3
  <td>
4
- <span href="#" title="%%SUCURI.AuditLog.DateTime%%"
5
- class="sucuriscan-label sucuriscan-auditlog-%%SUCURI.AuditLog.Event%%">
6
- %%SUCURI.AuditLog.EventTitle%%</span>
 
7
  </td>
8
  <td><span class="sucuriscan-monospace">%%SUCURI.AuditLog.Username%%</span></td>
9
  <td><span class="sucuriscan-monospace">%%SUCURI.AuditLog.RemoteAddress%%</span></td>
1
 
2
  <tr class="%%SUCURI.AuditLog.CssClass%%">
3
  <td>
4
+ <div class="sucuriscan-severity">
5
+ <span class="sucuriscan-label sucuriscan-auditlog-%%SUCURI.AuditLog.Event%%">%%SUCURI.AuditLog.EventTitle%%</span>
6
+ <span class="sucuriscan-tooltip sucuriscan-label sucuriscan-auditlog-%%SUCURI.AuditLog.Event%%">%%SUCURI.AuditLog.DateTime%%</span>
7
+ </div>
8
  </td>
9
  <td><span class="sucuriscan-monospace">%%SUCURI.AuditLog.Username%%</span></td>
10
  <td><span class="sucuriscan-monospace">%%SUCURI.AuditLog.RemoteAddress%%</span></td>
inc/tpl/integrity-auditreport.html.tpl CHANGED
@@ -6,13 +6,9 @@
6
 
7
  <div class="sucuriscan-inline-alert-info">
8
  <p>
9
- The data used to generate these charts come from the last <strong>%%SUCURI.AuditReport.Logs4Report%%
10
- audit logs</strong> of your site, you can configure this number from the plugin
11
- settings. The categorization of each event may change at anytime but will be
12
- associated to the severity of the performed action, this means that an event
13
- generated after an user interaction <em>(authentications, database modifications,
14
- website options)</em> will always be more severe than a simple notification or a
15
- change in the plugin settings.
16
  </p>
17
  </div>
18
 
6
 
7
  <div class="sucuriscan-inline-alert-info">
8
  <p>
9
+ The data used to generate these charts comes from the last <strong>%%SUCURI.AuditReport.Logs4Report%%
10
+ audit logs</strong>, you can configure this number from the plugin settings page,
11
+ you can also disable and enable this panel from there at any time.
 
 
 
 
12
  </p>
13
  </div>
14
 
inc/tpl/settings-general.html.tpl CHANGED
@@ -26,6 +26,18 @@
26
  monitoring tool forever even if you remove the API key and generate it again.
27
  </p>
28
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  <div class="sucuriscan-inline-alert-warning sucuriscan-%%SUCURI.InvalidDomainVisibility%%">
30
  <p>
31
  Your domain <code>%%SUCURI.CleanDomain%%</code> does not seems to have a DNS
@@ -140,18 +152,40 @@
140
  </tr>
141
 
142
  <tr>
143
- <td>Collect failed passwords</td>
144
- <td>%%SUCURI.CollectWrongPasswords%%</td>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
  <td class="td-with-button">
146
  <form action="%%SUCURI.URL.Settings%%" method="post">
147
  <input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
148
- <input type="text" name="sucuriscan_collect_wrong_passwords" class="input-text" placeholder="Type: YES or NO" />
149
- <button type="submit" class="button-primary">Change</button>
150
  </form>
151
  </td>
152
  </tr>
153
 
154
- <tr class="alternate">
155
  <td>Display audit report</td>
156
  <td>%%SUCURI.AuditReportStatus%%</td>
157
  <td class="td-with-button">
@@ -163,7 +197,7 @@
163
  </td>
164
  </tr>
165
 
166
- <tr>
167
  <td>Audit report limit</td>
168
  <td>Process latest %%SUCURI.AuditReportLimit%% logs</td>
169
  <td class="td-with-button">
@@ -175,26 +209,26 @@
175
  </td>
176
  </tr>
177
 
178
- <tr class="alternate">
179
- <td>Plugin advertisement</td>
180
- <td>%%SUCURI.AdsVisibility%%</td>
181
  <td class="td-with-button">
182
  <form action="%%SUCURI.URL.Settings%%" method="post">
183
  <input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
184
- <input type="text" name="sucuriscan_ads_visibility" class="input-text" placeholder="Type: SHOW or HIDE" />
185
  <button type="submit" class="button-primary">Change</button>
186
  </form>
187
  </td>
188
  </tr>
189
 
190
- <tr>
191
- <td>Support reverse proxy</td>
192
- <td>%%SUCURI.ReverseProxyStatus%%</td>
193
  <td class="td-with-button">
194
  <form action="%%SUCURI.URL.Settings%%" method="post">
195
  <input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
196
- <input type="hidden" name="sucuriscan_revproxy" value="%%SUCURI.ReverseProxySwitchValue%%" />
197
- <button type="submit" class="button-primary %%SUCURI.ReverseProxySwitchCssClass%%">%%SUCURI.ReverseProxySwitchText%%</button>
198
  </form>
199
  </td>
200
  </tr>
26
  monitoring tool forever even if you remove the API key and generate it again.
27
  </p>
28
 
29
+ <div class="sucuriscan-inline-alert-info">
30
+ <p>
31
+ All the HTTP requests used to communicate with the API service are being sent
32
+ using the WordPress built-in functions, so <em>(almost)</em> all its official
33
+ features are inherited, this is useful if you need to pass these HTTP requests
34
+ through a proxy. According to the <a href="http://codex.wordpress.org/HTTP_API"
35
+ target="_blank">official documentation</a> you have to add some constants to the
36
+ main configuration file: <em>WP_PROXY_HOST, WP_PROXY_PORT, WP_PROXY_USERNAME,
37
+ WP_PROXY_PASSWORD</em>.
38
+ </p>
39
+ </div>
40
+
41
  <div class="sucuriscan-inline-alert-warning sucuriscan-%%SUCURI.InvalidDomainVisibility%%">
42
  <p>
43
  Your domain <code>%%SUCURI.CleanDomain%%</code> does not seems to have a DNS
152
  </tr>
153
 
154
  <tr>
155
+ <td>API proxy host:port</td>
156
+ <td><span class="sucuriscan-monospace">%%SUCURI.APIProxy.Host%%:%%SUCURI.APIProxy.Port%%</span></td>
157
+ <td>&nbsp;</td>
158
+ </tr>
159
+
160
+ <tr class="alternate">
161
+ <td>API proxy username</td>
162
+ <td><span class="sucuriscan-monospace">%%SUCURI.APIProxy.Username%%</span></td>
163
+ <td>&nbsp;</td>
164
+ </tr>
165
+
166
+ <tr>
167
+ <td>API proxy password</td>
168
+ <td>
169
+ <span class="sucuriscan-label-%%SUCURI.APIProxy.PasswordType%%">
170
+ %%SUCURI.APIProxy.PasswordText%%
171
+ </span>
172
+ </td>
173
+ <td>&nbsp;</td>
174
+ </tr>
175
+
176
+ <tr class="alternate">
177
+ <td>Support reverse proxy</td>
178
+ <td>%%SUCURI.ReverseProxyStatus%%</td>
179
  <td class="td-with-button">
180
  <form action="%%SUCURI.URL.Settings%%" method="post">
181
  <input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
182
+ <input type="hidden" name="sucuriscan_revproxy" value="%%SUCURI.ReverseProxySwitchValue%%" />
183
+ <button type="submit" class="button-primary %%SUCURI.ReverseProxySwitchCssClass%%">%%SUCURI.ReverseProxySwitchText%%</button>
184
  </form>
185
  </td>
186
  </tr>
187
 
188
+ <tr>
189
  <td>Display audit report</td>
190
  <td>%%SUCURI.AuditReportStatus%%</td>
191
  <td class="td-with-button">
197
  </td>
198
  </tr>
199
 
200
+ <tr class="alternate">
201
  <td>Audit report limit</td>
202
  <td>Process latest %%SUCURI.AuditReportLimit%% logs</td>
203
  <td class="td-with-button">
209
  </td>
210
  </tr>
211
 
212
+ <tr>
213
+ <td>Collect failed passwords</td>
214
+ <td>%%SUCURI.CollectWrongPasswords%%</td>
215
  <td class="td-with-button">
216
  <form action="%%SUCURI.URL.Settings%%" method="post">
217
  <input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
218
+ <input type="text" name="sucuriscan_collect_wrong_passwords" class="input-text" placeholder="Type: YES or NO" />
219
  <button type="submit" class="button-primary">Change</button>
220
  </form>
221
  </td>
222
  </tr>
223
 
224
+ <tr class="alternate">
225
+ <td>Plugin advertisement</td>
226
+ <td>%%SUCURI.AdsVisibility%%</td>
227
  <td class="td-with-button">
228
  <form action="%%SUCURI.URL.Settings%%" method="post">
229
  <input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
230
+ <input type="text" name="sucuriscan_ads_visibility" class="input-text" placeholder="Type: SHOW or HIDE" />
231
+ <button type="submit" class="button-primary">Change</button>
232
  </form>
233
  </td>
234
  </tr>
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.6
7
- Tested up to: 4.1
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.6 =
356
  * Added audit log reporting.
357
  * Added more settings for better control.
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
7
+ Tested up to: 4.1.1
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.7.=
356
+ * Added better support for directory separators
357
+ * Added option to remove API key from plugin
358
+ * Various bugfixes and improvements
359
+
360
  = 1.7.6 =
361
  * Added audit log reporting.
362
  * Added more settings for better control.
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.6
8
  Author URI: http://sucuri.net
9
  */
10
 
@@ -15,7 +15,7 @@ Author URI: http://sucuri.net
15
  * @package Sucuri Security
16
  * @author Yorman Arias <yorman.arias@sucuri.net>
17
  * @author Daniel Cid <dcid@sucuri.net>
18
- * @copyright Since 2010-2014 Sucuri Inc.
19
  * @license Released under the GPL - see LICENSE file for details.
20
  * @link https://wordpress.sucuri.net/
21
  * @since File available since Release 0.1
@@ -66,7 +66,7 @@ define( 'SUCURISCAN', 'sucuriscan' );
66
  /**
67
  * Current version of the plugin's code.
68
  */
69
- define( 'SUCURISCAN_VERSION', '1.7.6' );
70
 
71
  /**
72
  * The name of the Sucuri plugin main file.
@@ -411,6 +411,10 @@ class SucuriScan {
411
  }
412
  }
413
 
 
 
 
 
414
  return $ini_value;
415
  }
416
 
@@ -543,6 +547,8 @@ class SucuriScan {
543
  }
544
  }
545
 
 
 
546
  return $wp_version;
547
  }
548
 
@@ -561,7 +567,7 @@ class SucuriScan {
561
  }
562
 
563
  // Remove duplicated double slashes.
564
- $file_path = realpath( $file_path );
565
 
566
  if ( $file_path ){
567
  return $file_path;
@@ -602,7 +608,7 @@ class SucuriScan {
602
  * @return string Secret key definition pattern.
603
  */
604
  public static function secret_key_pattern(){
605
- return '/define\(\'([A-Z_]+)\',(\s+)?\'(.*)\'\);/';
606
  }
607
 
608
  /**
@@ -834,8 +840,8 @@ class SucuriScan {
834
 
835
  $intervals = array(
836
  1 => array( 'year', 31556926, ),
837
- $diff < 31556926 => array( 'month', 2628000, ),
838
- $diff < 2629744 => array( 'week', 604800, ),
839
  $diff < 604800 => array( 'day', 86400, ),
840
  $diff < 86400 => array( 'hour', 3600, ),
841
  $diff < 3600 => array( 'minute', 60, ),
@@ -932,13 +938,19 @@ class SucuriScan {
932
  */
933
  public static function get_ip_info( $remote_addr = '' ){
934
  if ( $remote_addr ) {
935
- $addr_info = array();
936
  $ip_parts = explode( '/', $remote_addr );
937
- $addr_info['remote_addr'] = $ip_parts[0];
938
- $addr_info['cidr_range'] = isset($ip_parts[1]) ? $ip_parts[1] : '32';
939
- $addr_info['cidr_format'] = $addr_info['remote_addr'] . '/' . $addr_info['cidr_range'];
940
 
941
- return $addr_info;
 
 
 
 
 
 
 
 
 
 
942
  }
943
 
944
  return false;
@@ -974,8 +986,12 @@ class SucuriScan {
974
  */
975
  public static function get_valid_email( $email = '', $as_array = false ){
976
  $valid_emails = array();
 
977
 
978
- if ( strpos( $email, ',' ) !== false ){
 
 
 
979
  $addresses = explode( ',', $email );
980
 
981
  foreach ( $addresses as $address ){
@@ -987,12 +1003,17 @@ class SucuriScan {
987
  }
988
  }
989
 
990
- elseif ( self::is_valid_email( $email ) ){
 
 
 
991
  $valid_emails[] = $email;
992
  }
993
 
994
- if ( ! empty($valid_emails) ){
995
- if ( $as_array === true ){
 
 
996
  return $valid_emails;
997
  }
998
 
@@ -1042,8 +1063,8 @@ class SucuriScan {
1042
  */
1043
  public static function is_multi_list( $list = array() ){
1044
  if ( ! empty($list) ){
1045
- foreach ( $list as $item ){
1046
- if ( is_array( $item ) ){
1047
  return true;
1048
  }
1049
  }
@@ -1287,7 +1308,7 @@ class SucuriScanFileInfo extends SucuriScan {
1287
  */
1288
  public function get_directory_tree_md5( $directory = '', $as_array = false ){
1289
  $project_signatures = '';
1290
- $abs_path = rtrim( ABSPATH, '/' );
1291
  $files = $this->get_directory_tree( $directory );
1292
 
1293
  if ( $as_array ){
@@ -1302,7 +1323,7 @@ class SucuriScanFileInfo extends SucuriScan {
1302
  $filesize = @filesize( $filepath );
1303
 
1304
  if ( $as_array ){
1305
- $basename = str_replace( $abs_path . '/', '', $filepath );
1306
  $project_signatures[ $basename ] = array(
1307
  'filepath' => $filepath,
1308
  'checksum' => $file_checksum,
@@ -1311,7 +1332,7 @@ class SucuriScanFileInfo extends SucuriScan {
1311
  'modified_at' => @filemtime( $filepath ),
1312
  );
1313
  } else {
1314
- $filepath = str_replace( $abs_path, $abs_path . '/', $filepath );
1315
  $project_signatures .= sprintf(
1316
  "%s%s%s%s\n",
1317
  $file_checksum,
@@ -1432,7 +1453,7 @@ class SucuriScanFileInfo extends SucuriScan {
1432
  */
1433
  private function get_directory_tree_with_spl( $directory = '' ){
1434
  $files = array();
1435
- $filepath = realpath( $directory );
1436
 
1437
  if ( ! class_exists( 'FilesystemIterator' ) ){
1438
  return $this->get_directory_tree( $directory, 'opendir' );
@@ -1453,12 +1474,12 @@ class SucuriScanFileInfo extends SucuriScan {
1453
  }
1454
 
1455
  foreach ( $objects as $filepath => $fileinfo ){
 
 
1456
  if ( $this->run_recursively ){
1457
  $directory = dirname( $filepath );
1458
  $filename = $fileinfo->getFilename();
1459
  } else {
1460
- if ( $fileinfo->isDot() || $fileinfo->isDir() ){ continue; }
1461
-
1462
  $directory = $fileinfo->getPath();
1463
  $filename = $fileinfo->getFilename();
1464
  $filepath = $directory . '/' . $filename;
@@ -1489,7 +1510,7 @@ class SucuriScanFileInfo extends SucuriScan {
1489
 
1490
  if ( is_array( $files_found ) ){
1491
  foreach ( $files_found as $filepath ){
1492
- $filepath = realpath( $filepath );
1493
  $directory = dirname( $filepath );
1494
  $filepath_parts = explode( '/', $filepath );
1495
  $filename = array_pop( $filepath_parts );
@@ -1523,14 +1544,17 @@ class SucuriScanFileInfo extends SucuriScan {
1523
  * @return array List of files in the main and subdirectories of the folder specified.
1524
  */
1525
  private function get_directory_tree_with_opendir( $directory = '' ){
 
1526
  $dh = @opendir( $directory );
1527
- if ( ! $dh ){ return false; }
1528
 
1529
- $files = array();
 
1530
  while ( ($filename = readdir( $dh )) !== false ){
1531
- $filepath = realpath( $directory.'/'.$filename );
1532
 
1533
- if ( is_dir( $filepath ) ){
 
 
1534
  if ( $this->ignore_folderpath( $directory, $filename ) ){ continue; }
1535
 
1536
  if ( $this->run_recursively ){
@@ -1563,7 +1587,7 @@ class SucuriScanFileInfo extends SucuriScan {
1563
 
1564
  if ( $this->ignore_directories ){
1565
  // Ignore directories based on a common regular expression.
1566
- $filepath = realpath( $directory . '/' . $filename );
1567
  $pattern = '/\/wp-content\/(uploads|cache|backup|w3tc)/';
1568
 
1569
  if ( preg_match( $pattern, $filepath ) ){
@@ -2237,56 +2261,99 @@ class SucuriScanCache extends SucuriScan {
2237
  class SucuriScanOption extends SucuriScanRequest {
2238
 
2239
  /**
2240
- * Default values for the plugin options.
2241
  *
2242
- * @return array Default plugin option values.
2243
  */
2244
  public static function get_default_option_values(){
2245
  $defaults = array(
2246
- 'sucuriscan_api_key' => false,
2247
  'sucuriscan_account' => '',
 
 
 
 
 
2248
  'sucuriscan_datastore_path' => '',
2249
- 'sucuriscan_fs_scanner' => 'enabled',
2250
- 'sucuriscan_scan_frequency' => 'hourly',
2251
- 'sucuriscan_scan_interface' => 'spl',
2252
- 'sucuriscan_scan_modfiles' => 'disabled',
2253
- 'sucuriscan_scan_checksums' => 'enabled',
2254
- 'sucuriscan_scan_errorlogs' => 'disabled',
2255
- 'sucuriscan_sitecheck_scanner' => 'enabled',
2256
- 'sucuriscan_sitecheck_counter' => 0,
2257
- 'sucuriscan_parse_errorlogs' => 'enabled',
2258
  'sucuriscan_errorlogs_limit' => 30,
 
 
 
 
 
2259
  'sucuriscan_ignore_scanning' => 'disabled',
2260
- 'sucuriscan_runtime' => 0,
2261
- 'sucuriscan_lastlogin_redirection' => 'enabled',
2262
- 'sucuriscan_notify_to' => '',
2263
- 'sucuriscan_emails_sent' => 0,
2264
- 'sucuriscan_emails_per_hour' => 5,
2265
  'sucuriscan_last_email_at' => time(),
2266
- 'sucuriscan_email_subject' => 'Sucuri Alert, :domain, :event',
2267
- 'sucuriscan_prettify_mails' => 'disabled',
2268
- 'sucuriscan_notify_success_login' => 'enabled',
 
2269
  'sucuriscan_notify_failed_login' => 'enabled',
 
 
 
 
 
 
2270
  'sucuriscan_notify_post_publication' => 'enabled',
 
 
 
 
2271
  'sucuriscan_notify_theme_editor' => 'enabled',
2272
- 'sucuriscan_maximum_failed_logins' => 30,
2273
- 'sucuriscan_collect_wrong_passwords' => 'disabled',
2274
- 'sucuriscan_ignored_events' => '',
2275
- 'sucuriscan_verify_ssl_cert' => 'true',
 
 
 
 
 
2276
  'sucuriscan_request_timeout' => 90,
2277
- 'sucuriscan_heartbeat' => 'enabled',
2278
- 'sucuriscan_heartbeat_pulse' => 15,
2279
- 'sucuriscan_heartbeat_interval' => 'standard',
2280
- 'sucuriscan_heartbeat_autostart' => 'enabled',
2281
- 'sucuriscan_ads_visibility' => 'enabled',
2282
- 'sucuriscan_audit_report' => 'disabled',
2283
- 'sucuriscan_logs4report' => 500,
2284
  'sucuriscan_revproxy' => 'disabled',
 
 
 
 
 
 
 
 
 
 
2285
  );
2286
 
2287
  return $defaults;
2288
  }
2289
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2290
  /**
2291
  * Retrieve the default values for some specific options.
2292
  *
@@ -2766,7 +2833,6 @@ class SucuriScanEvent extends SucuriScan {
2766
  $hashes_sent = SucuriScanAPI::send_hashes( $signatures );
2767
 
2768
  if ( $hashes_sent ){
2769
- SucuriScanInterface::info( 'Successful filesystem scan' );
2770
  SucuriScanOption::update_option( ':runtime', time() );
2771
  return true;
2772
  } else {
@@ -5929,10 +5995,7 @@ class SucuriScanInterface {
5929
  wp_enqueue_style( 'sucuriscan' );
5930
  wp_enqueue_script( 'sucuriscan' );
5931
 
5932
- if (
5933
- SucuriScanRequest::get( 'page', 'sucuriscan' ) !== false
5934
- && SucuriScanOption::get_option( ':audit_report' ) !== 'disabled'
5935
- ) {
5936
  wp_register_script( 'sucuriscan2', SUCURISCAN_URL . '/inc/js/d3.v3.min.js', array(), $asset_version );
5937
  wp_register_script( 'sucuriscan3', SUCURISCAN_URL . '/inc/js/c3.min.js', array(), $asset_version );
5938
  wp_enqueue_script( 'sucuriscan2' );
@@ -6049,11 +6112,14 @@ class SucuriScanInterface {
6049
  LOCK_EX
6050
  );
6051
  } else {
 
6052
  SucuriScanInterface::error(
6053
- 'Data folder does not exists and could not be created. You will need to either
6054
- change the location of the directory from the generanl settings panel located
6055
- in the plugin settings page or create this directory manually and give it write
6056
- permissions:<code>' . $plugin_upload_folder . '</code>'
 
 
6057
  );
6058
  }
6059
  }
@@ -7927,7 +7993,7 @@ function sucuriscan_harden_errorlog(){
7927
  $sucuri_fileinfo = new SucuriScanFileInfo();
7928
  $sucuri_fileinfo->ignore_files = false;
7929
  $sucuri_fileinfo->ignore_directories = false;
7930
- $error_logs = $sucuri_fileinfo->find_file( 'error_log' );
7931
  $total_log_files = count( $error_logs );
7932
  } else {
7933
  $error_logs = array();
@@ -7964,6 +8030,7 @@ function sucuriscan_harden_errorlog(){
7964
  $description .= '</p><ul class="sucuriscan-list-as-table">';
7965
 
7966
  foreach ( $error_logs as $error_log_path ){
 
7967
  $description .= '<li>' . $error_log_path . '</li>';
7968
  }
7969
 
@@ -7998,9 +8065,9 @@ function sucuriscan_page(){
7998
 
7999
  $template_variables = array(
8000
  'WordpressVersion' => sucuriscan_wordpress_outdated(),
8001
- 'AuditLogs' => sucuriscan_auditlogs(),
8002
- 'AuditReports' => sucuriscan_auditreport(),
8003
  'CoreFiles' => sucuriscan_core_files(),
 
 
8004
  );
8005
 
8006
  echo SucuriScanTemplate::get_template( 'integrity', $template_variables );
@@ -8039,62 +8106,64 @@ function sucuriscan_integrity_form_submissions(){
8039
  'fixed' => 'Core file marked as fixed',
8040
  );
8041
 
8042
- foreach ( $integrity_files as $i => $file_path ){
8043
- $full_path = ABSPATH . $file_path;
8044
- $status_type = $integrity_types[ $i ];
8045
-
8046
- switch ( $integrity_action ){
8047
- case 'restore':
8048
- $file_content = SucuriScanAPI::get_original_core_file( $file_path );
8049
- if ( $file_content ){
8050
- $restored = @file_put_contents( $full_path, $file_content, LOCK_EX );
8051
- $files_processed += ( $restored ? 1 : 0 );
8052
- $files_affected[] = $full_path;
8053
- }
8054
- break;
8055
- case 'delete':
8056
- if ( @unlink( $full_path ) ){
8057
- $files_processed += 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
8058
  $files_affected[] = $full_path;
8059
- }
8060
- break;
8061
- case 'fixed':
8062
- $cache_key = md5( $file_path );
8063
- $cache_value = array(
8064
- 'file_path' => $file_path,
8065
- 'file_status' => $status_type,
8066
- 'ignored_at' => time(),
8067
- );
8068
- $cached = $cache->add( $cache_key, $cache_value );
8069
- $files_processed += ( $cached ? 1 : 0 );
8070
- $files_affected[] = $full_path;
8071
- break;
8072
  }
8073
- }
8074
 
8075
- // Report files affected as a single event.
8076
- if ( ! empty($files_affected) ) {
8077
- $message_tpl = ( count( $files_affected ) > 1 )
8078
- ? '%s: (multiple entries): %s'
8079
- : '%s: %s';
8080
- $message = sprintf(
8081
- $message_tpl,
8082
- $action_titles[ $integrity_action ],
8083
- @implode( ',', $files_affected )
8084
- );
8085
 
8086
- switch ( $integrity_action ){
8087
- case 'restore': SucuriScanEvent::report_info_event( $message ); break;
8088
- case 'delete': SucuriScanEvent::report_notice_event( $message ); break;
8089
- case 'fixed': SucuriScanEvent::report_warning_event( $message ); break;
 
8090
  }
8091
- }
8092
 
8093
- SucuriScanInterface::info(sprintf(
8094
- '<code>%d</code> out of <code>%d</code> files were successfully processed.',
8095
- $files_selected,
8096
- $files_processed
8097
- ));
 
8098
  }
8099
  }
8100
  }
@@ -8114,7 +8183,7 @@ function sucuriscan_get_integrity_tree( $dir = './', $recursive = false ){
8114
  $sucuri_fileinfo->ignore_files = false;
8115
  $sucuri_fileinfo->ignore_directories = false;
8116
  $sucuri_fileinfo->run_recursively = $recursive;
8117
- $sucuri_fileinfo->scan_interface = 'opendir';
8118
  $integrity_tree = $sucuri_fileinfo->get_directory_tree_md5( $dir, true );
8119
 
8120
  if ( ! $integrity_tree ){
@@ -8145,6 +8214,7 @@ function sucuriscan_auditlogs(){
8145
  'AuditLogs.NoItemsVisibility' => 'visible',
8146
  'AuditLogs.PaginationVisibility' => 'hidden',
8147
  'AuditLogs.PaginationLinks' => '',
 
8148
  );
8149
 
8150
  if ( $audit_logs ){
@@ -8153,6 +8223,13 @@ function sucuriscan_auditlogs(){
8153
  $iterator_start = ($page_number - 1) * $max_per_page;
8154
  $iterator_end = $total_items;
8155
 
 
 
 
 
 
 
 
8156
  for ( $i = $iterator_start; $i < $total_items; $i++ ){
8157
  if ( $counter_i > $max_per_page ){ break; }
8158
 
@@ -10560,7 +10637,7 @@ function sucuriscan_settings_general(){
10560
  'APIKey' => ( ! $api_key ? '<em>(not set)</em>' : $api_key ),
10561
  'APIKey.RecoverVisibility' => SucuriScanTemplate::visibility( ! $api_key && ! $display_manual_key_form ),
10562
  'APIKey.ManualKeyFormVisibility' => SucuriScanTemplate::visibility( $display_manual_key_form ),
10563
- 'APIKey.RemoveVisibility' => SucuriScanTemplate::visibility( $api_key ),
10564
  'InvalidDomainVisibility' => SucuriScanTemplate::visibility( $invalid_domain ),
10565
  'NotifyTo' => SucuriScanOption::get_option( ':notify_to' ),
10566
  'EmailsPerHour' => 'Undefined',
@@ -10584,6 +10661,13 @@ function sucuriscan_settings_general(){
10584
  'ReverseProxySwitchText' => 'Disable',
10585
  'ReverseProxySwitchValue' => 'disable',
10586
  'ReverseProxySwitchCssClass' => 'button-danger',
 
 
 
 
 
 
 
10587
  );
10588
 
10589
  if ( array_key_exists( $emails_per_hour, $sucuriscan_emails_per_hour ) ){
@@ -10616,6 +10700,26 @@ function sucuriscan_settings_general(){
10616
  $template_variables['CollectWrongPasswords'] = '<span class="sucuriscan-label-error">Yes, collect passwords</span>';
10617
  }
10618
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10619
  return SucuriScanTemplate::get_section( 'settings-general', $template_variables );
10620
  }
10621
 
@@ -11428,11 +11532,16 @@ function sucuriscan_infosys_errorlogs(){
11428
  'ErrorLog.List' => '',
11429
  );
11430
 
11431
- $error_log_path = realpath( ABSPATH . '/error_log' );
 
11432
  $errorlogs_limit = SucuriScanOption::get_option( ':errorlogs_limit' );
11433
  $template_variables['ErrorLog.LogsLimit'] = $errorlogs_limit;
11434
  $errorlogs_counter = 0;
11435
 
 
 
 
 
11436
  if ( SucuriScanOption::get_option( ':parse_errorlogs' ) === 'disabled' ) {
11437
  $template_variables['ErrorLog.DisabledVisibility'] = 'visible';
11438
  }
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.7
8
  Author URI: http://sucuri.net
9
  */
10
 
15
  * @package Sucuri Security
16
  * @author Yorman Arias <yorman.arias@sucuri.net>
17
  * @author Daniel Cid <dcid@sucuri.net>
18
+ * @copyright Since 2010-2015 Sucuri Inc.
19
  * @license Released under the GPL - see LICENSE file for details.
20
  * @link https://wordpress.sucuri.net/
21
  * @since File available since Release 0.1
66
  /**
67
  * Current version of the plugin's code.
68
  */
69
+ define( 'SUCURISCAN_VERSION', '1.7.7' );
70
 
71
  /**
72
  * The name of the Sucuri plugin main file.
411
  }
412
  }
413
 
414
+ if ( $property == 'error_log' ) {
415
+ $ini_value = basename( $ini_value );
416
+ }
417
+
418
  return $ini_value;
419
  }
420
 
547
  }
548
  }
549
 
550
+ $wp_version = self::escape( $wp_version );
551
+
552
  return $wp_version;
553
  }
554
 
567
  }
568
 
569
  // Remove duplicated double slashes.
570
+ $file_path = @realpath( $file_path );
571
 
572
  if ( $file_path ){
573
  return $file_path;
608
  * @return string Secret key definition pattern.
609
  */
610
  public static function secret_key_pattern(){
611
+ return '/define\((\s+)?\'([A-Z_]+)\',(\s+)?\'(.*)\'(\s+)?\);/';
612
  }
613
 
614
  /**
840
 
841
  $intervals = array(
842
  1 => array( 'year', 31556926, ),
843
+ $diff < 31556926 => array( 'month', 2592000, ),
844
+ $diff < 2592000 => array( 'week', 604800, ),
845
  $diff < 604800 => array( 'day', 86400, ),
846
  $diff < 86400 => array( 'hour', 3600, ),
847
  $diff < 3600 => array( 'minute', 60, ),
938
  */
939
  public static function get_ip_info( $remote_addr = '' ){
940
  if ( $remote_addr ) {
 
941
  $ip_parts = explode( '/', $remote_addr );
 
 
 
942
 
943
+ if (
944
+ array_key_exists( 0, $ip_parts )
945
+ && self::is_valid_ip( $ip_parts[0] )
946
+ ) {
947
+ $addr_info = array();
948
+ $addr_info['remote_addr'] = $ip_parts[0];
949
+ $addr_info['cidr_range'] = isset($ip_parts[1]) ? $ip_parts[1] : '32';
950
+ $addr_info['cidr_format'] = $addr_info['remote_addr'] . '/' . $addr_info['cidr_range'];
951
+
952
+ return $addr_info;
953
+ }
954
  }
955
 
956
  return false;
986
  */
987
  public static function get_valid_email( $email = '', $as_array = false ){
988
  $valid_emails = array();
989
+ $is_valid_string = (bool) ( is_string( $email ) && ! empty($email) );
990
 
991
+ if (
992
+ $is_valid_string === true
993
+ && strpos( $email, ',' ) !== false
994
+ ) {
995
  $addresses = explode( ',', $email );
996
 
997
  foreach ( $addresses as $address ){
1003
  }
1004
  }
1005
 
1006
+ elseif (
1007
+ $is_valid_string === true
1008
+ && self::is_valid_email( $email )
1009
+ ) {
1010
  $valid_emails[] = $email;
1011
  }
1012
 
1013
+ if ( ! empty($valid_emails) ) {
1014
+ $valid_emails = array_unique( $valid_emails );
1015
+
1016
+ if ( $as_array === true ) {
1017
  return $valid_emails;
1018
  }
1019
 
1063
  */
1064
  public static function is_multi_list( $list = array() ){
1065
  if ( ! empty($list) ){
1066
+ foreach ( (array) $list as $item ) {
1067
+ if ( is_array( $item ) ) {
1068
  return true;
1069
  }
1070
  }
1308
  */
1309
  public function get_directory_tree_md5( $directory = '', $as_array = false ){
1310
  $project_signatures = '';
1311
+ $abs_path = rtrim( ABSPATH, DIRECTORY_SEPARATOR );
1312
  $files = $this->get_directory_tree( $directory );
1313
 
1314
  if ( $as_array ){
1323
  $filesize = @filesize( $filepath );
1324
 
1325
  if ( $as_array ){
1326
+ $basename = str_replace( $abs_path . DIRECTORY_SEPARATOR, '', $filepath );
1327
  $project_signatures[ $basename ] = array(
1328
  'filepath' => $filepath,
1329
  'checksum' => $file_checksum,
1332
  'modified_at' => @filemtime( $filepath ),
1333
  );
1334
  } else {
1335
+ $filepath = str_replace( $abs_path, $abs_path . DIRECTORY_SEPARATOR, $filepath );
1336
  $project_signatures .= sprintf(
1337
  "%s%s%s%s\n",
1338
  $file_checksum,
1453
  */
1454
  private function get_directory_tree_with_spl( $directory = '' ){
1455
  $files = array();
1456
+ $filepath = @realpath( $directory );
1457
 
1458
  if ( ! class_exists( 'FilesystemIterator' ) ){
1459
  return $this->get_directory_tree( $directory, 'opendir' );
1474
  }
1475
 
1476
  foreach ( $objects as $filepath => $fileinfo ){
1477
+ if ( $fileinfo->isDir() ) { continue; }
1478
+
1479
  if ( $this->run_recursively ){
1480
  $directory = dirname( $filepath );
1481
  $filename = $fileinfo->getFilename();
1482
  } else {
 
 
1483
  $directory = $fileinfo->getPath();
1484
  $filename = $fileinfo->getFilename();
1485
  $filepath = $directory . '/' . $filename;
1510
 
1511
  if ( is_array( $files_found ) ){
1512
  foreach ( $files_found as $filepath ){
1513
+ $filepath = @realpath( $filepath );
1514
  $directory = dirname( $filepath );
1515
  $filepath_parts = explode( '/', $filepath );
1516
  $filename = array_pop( $filepath_parts );
1544
  * @return array List of files in the main and subdirectories of the folder specified.
1545
  */
1546
  private function get_directory_tree_with_opendir( $directory = '' ){
1547
+ $files = array();
1548
  $dh = @opendir( $directory );
 
1549
 
1550
+ if ( ! $dh ) { return false; }
1551
+
1552
  while ( ($filename = readdir( $dh )) !== false ){
1553
+ $filepath = @realpath( $directory . '/' . $filename );
1554
 
1555
+ if ( $filepath === false ) {
1556
+ continue;
1557
+ } elseif ( is_dir( $filepath ) ){
1558
  if ( $this->ignore_folderpath( $directory, $filename ) ){ continue; }
1559
 
1560
  if ( $this->run_recursively ){
1587
 
1588
  if ( $this->ignore_directories ){
1589
  // Ignore directories based on a common regular expression.
1590
+ $filepath = @realpath( $directory . '/' . $filename );
1591
  $pattern = '/\/wp-content\/(uploads|cache|backup|w3tc)/';
1592
 
1593
  if ( preg_match( $pattern, $filepath ) ){
2261
  class SucuriScanOption extends SucuriScanRequest {
2262
 
2263
  /**
2264
+ * Default values for all the plugin's options.
2265
  *
2266
+ * @return array Default values for all the plugin's options.
2267
  */
2268
  public static function get_default_option_values(){
2269
  $defaults = array(
 
2270
  'sucuriscan_account' => '',
2271
+ 'sucuriscan_ads_visibility' => 'enabled',
2272
+ 'sucuriscan_api_key' => false,
2273
+ 'sucuriscan_audit_report' => 'disabled',
2274
+ 'sucuriscan_cloudproxy_apikey' => '',
2275
+ 'sucuriscan_collect_wrong_passwords' => 'disabled',
2276
  'sucuriscan_datastore_path' => '',
2277
+ 'sucuriscan_email_subject' => 'Sucuri Alert, :domain, :event',
2278
+ 'sucuriscan_emails_per_hour' => 5,
2279
+ 'sucuriscan_emails_sent' => 0,
 
 
 
 
 
 
2280
  'sucuriscan_errorlogs_limit' => 30,
2281
+ 'sucuriscan_fs_scanner' => 'enabled',
2282
+ 'sucuriscan_heartbeat' => 'enabled',
2283
+ 'sucuriscan_heartbeat_autostart' => 'enabled',
2284
+ 'sucuriscan_heartbeat_interval' => 'standard',
2285
+ 'sucuriscan_heartbeat_pulse' => 15,
2286
  'sucuriscan_ignore_scanning' => 'disabled',
2287
+ 'sucuriscan_ignored_events' => '',
 
 
 
 
2288
  'sucuriscan_last_email_at' => time(),
2289
+ 'sucuriscan_lastlogin_redirection' => 'enabled',
2290
+ 'sucuriscan_logs4report' => 500,
2291
+ 'sucuriscan_maximum_failed_logins' => 30,
2292
+ 'sucuriscan_notify_bruteforce_attack' => 'disabled',
2293
  'sucuriscan_notify_failed_login' => 'enabled',
2294
+ 'sucuriscan_notify_plugin_activated' => 'disabled',
2295
+ 'sucuriscan_notify_plugin_change' => 'disabled',
2296
+ 'sucuriscan_notify_plugin_deactivated' => 'disabled',
2297
+ 'sucuriscan_notify_plugin_deleted' => 'disabled',
2298
+ 'sucuriscan_notify_plugin_installed' => 'disabled',
2299
+ 'sucuriscan_notify_plugin_updated' => 'disabled',
2300
  'sucuriscan_notify_post_publication' => 'enabled',
2301
+ 'sucuriscan_notify_settings_updated' => 'disabled',
2302
+ 'sucuriscan_notify_success_login' => 'enabled',
2303
+ 'sucuriscan_notify_theme_activated' => 'disabled',
2304
+ 'sucuriscan_notify_theme_deleted' => 'disabled',
2305
  'sucuriscan_notify_theme_editor' => 'enabled',
2306
+ 'sucuriscan_notify_theme_installed' => 'disabled',
2307
+ 'sucuriscan_notify_theme_updated' => 'disabled',
2308
+ 'sucuriscan_notify_to' => '',
2309
+ 'sucuriscan_notify_user_registration' => 'disabled',
2310
+ 'sucuriscan_notify_website_updated' => 'disabled',
2311
+ 'sucuriscan_notify_widget_added' => 'disabled',
2312
+ 'sucuriscan_notify_widget_deleted' => 'disabled',
2313
+ 'sucuriscan_parse_errorlogs' => 'enabled',
2314
+ 'sucuriscan_prettify_mails' => 'disabled',
2315
  'sucuriscan_request_timeout' => 90,
 
 
 
 
 
 
 
2316
  'sucuriscan_revproxy' => 'disabled',
2317
+ 'sucuriscan_runtime' => 0,
2318
+ 'sucuriscan_scan_checksums' => 'enabled',
2319
+ 'sucuriscan_scan_errorlogs' => 'disabled',
2320
+ 'sucuriscan_scan_frequency' => 'twicedaily',
2321
+ 'sucuriscan_scan_interface' => 'spl',
2322
+ 'sucuriscan_scan_modfiles' => 'disabled',
2323
+ 'sucuriscan_site_version' => '0.0',
2324
+ 'sucuriscan_sitecheck_counter' => 0,
2325
+ 'sucuriscan_sitecheck_scanner' => 'enabled',
2326
+ 'sucuriscan_verify_ssl_cert' => 'true',
2327
  );
2328
 
2329
  return $defaults;
2330
  }
2331
 
2332
+ /**
2333
+ * Name of all valid plugin's options.
2334
+ *
2335
+ * @return array Name of all valid plugin's options.
2336
+ */
2337
+ public static function get_default_option_names() {
2338
+ $options = self::get_default_option_values();
2339
+ $names = array_keys( $options );
2340
+
2341
+ return $names;
2342
+ }
2343
+
2344
+ /**
2345
+ * Check whether an option is used in the plugin or not.
2346
+ *
2347
+ * @param string $option_name Name of the option that will be checked.
2348
+ * @return boolean True if the option is part of the plugin, False otherwise.
2349
+ */
2350
+ public static function is_valid_plugin_option( $option_name = '' ) {
2351
+ $valid_options = self::get_default_option_names();
2352
+ $is_valid_option = (bool) array_key_exists( $option_name, $valid_options );
2353
+
2354
+ return $is_valid_option;
2355
+ }
2356
+
2357
  /**
2358
  * Retrieve the default values for some specific options.
2359
  *
2833
  $hashes_sent = SucuriScanAPI::send_hashes( $signatures );
2834
 
2835
  if ( $hashes_sent ){
 
2836
  SucuriScanOption::update_option( ':runtime', time() );
2837
  return true;
2838
  } else {
5995
  wp_enqueue_style( 'sucuriscan' );
5996
  wp_enqueue_script( 'sucuriscan' );
5997
 
5998
+ if ( SucuriScanRequest::get( 'page', 'sucuriscan' ) !== false ) {
 
 
 
5999
  wp_register_script( 'sucuriscan2', SUCURISCAN_URL . '/inc/js/d3.v3.min.js', array(), $asset_version );
6000
  wp_register_script( 'sucuriscan3', SUCURISCAN_URL . '/inc/js/c3.min.js', array(), $asset_version );
6001
  wp_enqueue_script( 'sucuriscan2' );
6112
  LOCK_EX
6113
  );
6114
  } else {
6115
+ SucuriScanOption::delete_option( ':datastore_path' );
6116
  SucuriScanInterface::error(
6117
+ 'Data folder does not exists and could not be created. Try to <a href="' .
6118
+ SucuriScanTemplate::get_url( 'settings' ) . '">click this link</a> to see
6119
+ if the plugin is able to fix this error automatically, if this message
6120
+ reappears you will need to either change the location of the directory from
6121
+ the plugin general settings page or create this directory manually and give it
6122
+ write permissions:<code>' . $plugin_upload_folder . '</code>.'
6123
  );
6124
  }
6125
  }
7993
  $sucuri_fileinfo = new SucuriScanFileInfo();
7994
  $sucuri_fileinfo->ignore_files = false;
7995
  $sucuri_fileinfo->ignore_directories = false;
7996
+ $error_logs = $sucuri_fileinfo->find_file( $log_filename );
7997
  $total_log_files = count( $error_logs );
7998
  } else {
7999
  $error_logs = array();
8030
  $description .= '</p><ul class="sucuriscan-list-as-table">';
8031
 
8032
  foreach ( $error_logs as $error_log_path ){
8033
+ $error_log_path = str_replace( ABSPATH, '/', $error_log_path );
8034
  $description .= '<li>' . $error_log_path . '</li>';
8035
  }
8036
 
8065
 
8066
  $template_variables = array(
8067
  'WordpressVersion' => sucuriscan_wordpress_outdated(),
 
 
8068
  'CoreFiles' => sucuriscan_core_files(),
8069
+ 'AuditReports' => sucuriscan_auditreport(),
8070
+ 'AuditLogs' => sucuriscan_auditlogs(),
8071
  );
8072
 
8073
  echo SucuriScanTemplate::get_template( 'integrity', $template_variables );
8106
  'fixed' => 'Core file marked as fixed',
8107
  );
8108
 
8109
+ if ( $integrity_files ) {
8110
+ foreach ( (array) $integrity_files as $i => $file_path ){
8111
+ $full_path = ABSPATH . $file_path;
8112
+ $status_type = $integrity_types[ $i ];
8113
+
8114
+ switch ( $integrity_action ){
8115
+ case 'restore':
8116
+ $file_content = SucuriScanAPI::get_original_core_file( $file_path );
8117
+ if ( $file_content ){
8118
+ $restored = @file_put_contents( $full_path, $file_content, LOCK_EX );
8119
+ $files_processed += ( $restored ? 1 : 0 );
8120
+ $files_affected[] = $full_path;
8121
+ }
8122
+ break;
8123
+ case 'delete':
8124
+ if ( @unlink( $full_path ) ){
8125
+ $files_processed += 1;
8126
+ $files_affected[] = $full_path;
8127
+ }
8128
+ break;
8129
+ case 'fixed':
8130
+ $cache_key = md5( $file_path );
8131
+ $cache_value = array(
8132
+ 'file_path' => $file_path,
8133
+ 'file_status' => $status_type,
8134
+ 'ignored_at' => time(),
8135
+ );
8136
+ $cached = $cache->add( $cache_key, $cache_value );
8137
+ $files_processed += ( $cached ? 1 : 0 );
8138
  $files_affected[] = $full_path;
8139
+ break;
8140
+ }
 
 
 
 
 
 
 
 
 
 
 
8141
  }
 
8142
 
8143
+ // Report files affected as a single event.
8144
+ if ( ! empty($files_affected) ) {
8145
+ $message_tpl = ( count( $files_affected ) > 1 )
8146
+ ? '%s: (multiple entries): %s'
8147
+ : '%s: %s';
8148
+ $message = sprintf(
8149
+ $message_tpl,
8150
+ $action_titles[ $integrity_action ],
8151
+ @implode( ',', $files_affected )
8152
+ );
8153
 
8154
+ switch ( $integrity_action ){
8155
+ case 'restore': SucuriScanEvent::report_info_event( $message ); break;
8156
+ case 'delete': SucuriScanEvent::report_notice_event( $message ); break;
8157
+ case 'fixed': SucuriScanEvent::report_warning_event( $message ); break;
8158
+ }
8159
  }
 
8160
 
8161
+ SucuriScanInterface::info(sprintf(
8162
+ '<code>%d</code> out of <code>%d</code> files were successfully processed.',
8163
+ $files_selected,
8164
+ $files_processed
8165
+ ));
8166
+ }
8167
  }
8168
  }
8169
  }
8183
  $sucuri_fileinfo->ignore_files = false;
8184
  $sucuri_fileinfo->ignore_directories = false;
8185
  $sucuri_fileinfo->run_recursively = $recursive;
8186
+ $sucuri_fileinfo->scan_interface = SucuriScanOption::get_option( ':scan_interface' );
8187
  $integrity_tree = $sucuri_fileinfo->get_directory_tree_md5( $dir, true );
8188
 
8189
  if ( ! $integrity_tree ){
8214
  'AuditLogs.NoItemsVisibility' => 'visible',
8215
  'AuditLogs.PaginationVisibility' => 'hidden',
8216
  'AuditLogs.PaginationLinks' => '',
8217
+ 'AuditLogs.EnableAuditReportVisibility' => 'hidden',
8218
  );
8219
 
8220
  if ( $audit_logs ){
8223
  $iterator_start = ($page_number - 1) * $max_per_page;
8224
  $iterator_end = $total_items;
8225
 
8226
+ if (
8227
+ $audit_logs->total_entries >= $max_per_page
8228
+ && SucuriScanOption::get_option( ':audit_report' ) !== 'enabled'
8229
+ ) {
8230
+ $template_variables['AuditLogs.EnableAuditReportVisibility'] = 'visible';
8231
+ }
8232
+
8233
  for ( $i = $iterator_start; $i < $total_items; $i++ ){
8234
  if ( $counter_i > $max_per_page ){ break; }
8235
 
10637
  'APIKey' => ( ! $api_key ? '<em>(not set)</em>' : $api_key ),
10638
  'APIKey.RecoverVisibility' => SucuriScanTemplate::visibility( ! $api_key && ! $display_manual_key_form ),
10639
  'APIKey.ManualKeyFormVisibility' => SucuriScanTemplate::visibility( $display_manual_key_form ),
10640
+ 'APIKey.RemoveVisibility' => SucuriScanTemplate::visibility( (bool) $api_key ),
10641
  'InvalidDomainVisibility' => SucuriScanTemplate::visibility( $invalid_domain ),
10642
  'NotifyTo' => SucuriScanOption::get_option( ':notify_to' ),
10643
  'EmailsPerHour' => 'Undefined',
10661
  'ReverseProxySwitchText' => 'Disable',
10662
  'ReverseProxySwitchValue' => 'disable',
10663
  'ReverseProxySwitchCssClass' => 'button-danger',
10664
+ /* API Proxy Settings */
10665
+ 'APIProxy.Host' => 'n/a',
10666
+ 'APIProxy.Port' => 'n/a',
10667
+ 'APIProxy.Username' => 'n/a',
10668
+ 'APIProxy.Password' => 'n/a',
10669
+ 'APIProxy.PasswordType' => 'default',
10670
+ 'APIProxy.PasswordText' => 'empty',
10671
  );
10672
 
10673
  if ( array_key_exists( $emails_per_hour, $sucuriscan_emails_per_hour ) ){
10700
  $template_variables['CollectWrongPasswords'] = '<span class="sucuriscan-label-error">Yes, collect passwords</span>';
10701
  }
10702
 
10703
+ // Determine if the API calls with pass through a proxy or not.
10704
+ if ( class_exists( 'WP_HTTP_Proxy' ) ) {
10705
+ $wp_http_proxy = new WP_HTTP_Proxy();
10706
+
10707
+ if ( $wp_http_proxy->is_enabled() ) {
10708
+ $proxy_host = SucuriScan::escape( $wp_http_proxy->host() );
10709
+ $proxy_port = SucuriScan::escape( $wp_http_proxy->port() );
10710
+ $proxy_username = SucuriScan::escape( $wp_http_proxy->username() );
10711
+ $proxy_password = SucuriScan::escape( $wp_http_proxy->password() );
10712
+
10713
+ $template_variables['APIProxy.Host'] = $proxy_host;
10714
+ $template_variables['APIProxy.Port'] = $proxy_port;
10715
+ $template_variables['APIProxy.Username'] = $proxy_username;
10716
+ $template_variables['APIProxy.Password'] = $proxy_password;
10717
+ $template_variables['APIProxy.PasswordType'] = 'info';
10718
+ $template_variables['APIProxy.PasswordText'] = 'hidden';
10719
+
10720
+ }
10721
+ }
10722
+
10723
  return SucuriScanTemplate::get_section( 'settings-general', $template_variables );
10724
  }
10725
 
11532
  'ErrorLog.List' => '',
11533
  );
11534
 
11535
+ $error_log_path = false;
11536
+ $log_filename = SucuriScan::ini_get( 'error_log' );
11537
  $errorlogs_limit = SucuriScanOption::get_option( ':errorlogs_limit' );
11538
  $template_variables['ErrorLog.LogsLimit'] = $errorlogs_limit;
11539
  $errorlogs_counter = 0;
11540
 
11541
+ if ( $log_filename ) {
11542
+ $error_log_path = @realpath( ABSPATH . '/' . $log_filename );
11543
+ }
11544
+
11545
  if ( SucuriScanOption::get_option( ':parse_errorlogs' ) === 'disabled' ) {
11546
  $template_variables['ErrorLog.DisabledVisibility'] = 'visible';
11547
  }