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

Version Description

  • Added error message when storage is not writable
  • Fixed option getter to migrate plugin settings if possible
  • Fixed base directory name without PHP DIR constant
  • Fixed user authentication denial when no blocked users
  • Fixed htaccess standard rules checker with no WP_Rewrite
Download this release

Release Info

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

Code changes from version 1.7.19 to 1.8.0

Files changed (2) hide show
  1. readme.txt +8 -1
  2. sucuri.php +88 -31
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: dd@sucuri.net
3
  Donate Link: https://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.19
7
  Tested up to: 4.5.3
8
 
9
  The Sucuri WordPress Security plugin is a security toolset for security integrity monitoring, malware detection and security hardening.
@@ -354,6 +354,13 @@ service from the WordPress dashboard.
354
 
355
  == Changelog ==
356
 
 
 
 
 
 
 
 
357
  = 1.7.19 =
358
  * Added function to rescue HTTP requests using sockets
359
  * Fixed mishandled JSON data in audit logs Ajax request
3
  Donate Link: https://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.8.0
7
  Tested up to: 4.5.3
8
 
9
  The Sucuri WordPress Security plugin is a security toolset for security integrity monitoring, malware detection and security hardening.
354
 
355
  == Changelog ==
356
 
357
+ = 1.8.0 =
358
+ * Added error message when storage is not writable
359
+ * Fixed option getter to migrate plugin settings if possible
360
+ * Fixed base directory name without PHP __DIR__ constant
361
+ * Fixed user authentication denial when no blocked users
362
+ * Fixed htaccess standard rules checker with no WP_Rewrite
363
+
364
  = 1.7.19 =
365
  * Added function to rescue HTTP requests using sockets
366
  * Fixed mishandled JSON data in audit logs Ajax request
sucuri.php CHANGED
@@ -4,7 +4,7 @@ Plugin Name: Sucuri Security - Auditing, Malware Scanner and Hardening
4
  Plugin URI: https://wordpress.sucuri.net/
5
  Description: The <a href="https://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.19
8
  Author URI: https://sucuri.net
9
  */
10
 
@@ -65,7 +65,7 @@ define('SUCURISCAN', 'sucuriscan');
65
  /**
66
  * Current version of the plugin's code.
67
  */
68
- define('SUCURISCAN_VERSION', '1.7.19');
69
 
70
  /**
71
  * The name of the Sucuri plugin main file.
@@ -74,8 +74,14 @@ define('SUCURISCAN_PLUGIN_FILE', 'sucuri.php');
74
 
75
  /**
76
  * The name of the folder where the plugin's files will be located.
 
 
 
 
 
 
77
  */
78
- define('SUCURISCAN_PLUGIN_FOLDER', basename(__DIR__));
79
 
80
  /**
81
  * The fullpath where the plugin's files will be located.
@@ -1847,6 +1853,8 @@ class SucuriScanFileInfo extends SucuriScan
1847
  }
1848
 
1849
  if (is_array($tree) && !empty($tree)) {
 
 
1850
  return array_map(array('SucuriScan', 'fixPath'), $tree);
1851
  }
1852
  }
@@ -2165,12 +2173,15 @@ class SucuriScanFileInfo extends SucuriScan
2165
  foreach ($dir_tree as $filepath) {
2166
  $dir_path = dirname($filepath);
2167
 
2168
- if (is_array($dirs)
2169
- && !in_array($dir_path, $dirs)
2170
- && array_key_exists('directories', $this->ignored_directories)
2171
- && is_array($this->ignored_directories['directories'])
2172
- && !in_array($dir_path, $this->ignored_directories['directories'])
2173
- ) {
 
 
 
2174
  $dirs[] = $dir_path;
2175
  }
2176
  }
@@ -3146,14 +3157,21 @@ class SucuriScanOption extends SucuriScanRequest
3146
  * If the option is not in the external file nor in the database, and
3147
  * the name starts with the same prefix used by the plugin then we must
3148
  * return the default value defined by the author.
 
 
 
 
3149
  */
3150
  if (function_exists('get_option')) {
3151
  $value = get_option($option);
3152
 
3153
  if ($value !== false) {
3154
  if (strpos($option, 'sucuriscan_') === 0) {
3155
- delete_option($option);
3156
- self::update_option($option, $value);
 
 
 
3157
  }
3158
 
3159
  return $value;
@@ -5076,6 +5094,22 @@ class SucuriScanAPI extends SucuriScanOption
5076
  return substr($trail, 1);
5077
  }
5078
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5079
  /**
5080
  * Assign the communication protocol.
5081
  *
@@ -5298,8 +5332,11 @@ class SucuriScanAPI extends SucuriScanOption
5298
  curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
5299
  curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $timeout);
5300
  curl_setopt($curl, CURLOPT_TIMEOUT, $timeout * 2);
5301
- curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
5302
- curl_setopt($curl, CURLOPT_MAXREDIRS, 2);
 
 
 
5303
 
5304
  if ($method === 'POST') {
5305
  curl_setopt($curl, CURLOPT_POST, true);
@@ -12544,7 +12581,10 @@ class SucuriScanBlockedUsers extends SucuriScanLastLogins
12544
  $blocked = $cache->getAll();
12545
  $cache_key = md5($username);
12546
 
12547
- if (array_key_exists($cache_key, $blocked)) {
 
 
 
12548
  $blocked[$cache_key]->last_attempt = time();
12549
  $cache->set($cache_key, $blocked[$cache_key]);
12550
 
@@ -12612,21 +12652,6 @@ function sucuriscan_settings_form_submissions($page_nonce = null)
12612
  }
12613
 
12614
  if ($page_nonce) {
12615
- // Save API key after it was recovered by the administrator.
12616
- if ($api_key = SucuriScanRequest::post(':manual_api_key')) {
12617
- SucuriScanAPI::setPluginKey($api_key, true);
12618
- SucuriScanEvent::schedule_task();
12619
- SucuriScanEvent::report_info_event('Sucuri API key was added manually.');
12620
- }
12621
-
12622
- // Remove API key from the local storage.
12623
- if (SucuriScanRequest::post(':remove_api_key') !== false) {
12624
- SucuriScanAPI::setPluginKey('');
12625
- wp_clear_scheduled_hook('sucuriscan_scheduled_scan');
12626
- SucuriScanEvent::report_critical_event('Sucuri API key was deleted.');
12627
- SucuriScanEvent::notify_event('plugin_change', 'Sucuri API key removed');
12628
- }
12629
-
12630
  // Enable or disable the filesystem scanner.
12631
  if ($fs_scanner = SucuriScanRequest::post(':fs_scanner', '(en|dis)able')) {
12632
  $action_d = $fs_scanner . 'd';
@@ -12899,6 +12924,33 @@ function sucuriscan_settings_general_apikey($nonce)
12899
  $display_manual_key_form = (bool) (SucuriScanRequest::post(':recover_key') !== false);
12900
 
12901
  if ($nonce) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12902
  if (SucuriScanRequest::post(':plugin_api_key') !== false) {
12903
  $user_id = SucuriScanRequest::post(':setup_user');
12904
  $user_obj = SucuriScan::get_user_by_id($user_id);
@@ -14755,11 +14807,16 @@ function sucuriscan_htaccess_is_standard($rules = false)
14755
  }
14756
  }
14757
 
14758
- if (is_string($rules) && !empty($rules)) {
 
 
 
14759
  $rewrite = new WP_Rewrite();
14760
  $standard = $rewrite->mod_rewrite_rules();
14761
 
14762
- return (bool) (strpos($rules, $standard) !== false);
 
 
14763
  }
14764
 
14765
  return false;
4
  Plugin URI: https://wordpress.sucuri.net/
5
  Description: The <a href="https://sucuri.net/" target="_blank">Sucuri</a> plugin provides the website owner the best Activity Auditing, SiteCheck Remote Malware Scanning, Effective Security Hardening and Post-Hack features. SiteCheck will check for malware, spam, blacklisting and other security issues like .htaccess redirects, hidden eval code, etc. The best thing about it is it's completely free.
6
  Author: Sucuri, INC
7
+ Version: 1.8.0
8
  Author URI: https://sucuri.net
9
  */
10
 
65
  /**
66
  * Current version of the plugin's code.
67
  */
68
+ define('SUCURISCAN_VERSION', '1.8.0');
69
 
70
  /**
71
  * The name of the Sucuri plugin main file.
74
 
75
  /**
76
  * The name of the folder where the plugin's files will be located.
77
+ *
78
+ * Note that we are using the constant FILE instead of DIR because some
79
+ * installations of PHP are either outdated or are not supporting the access to
80
+ * that definition, to keep things simple we will select the name of the
81
+ * directory name of the current file, then select the base name of that
82
+ * directory.
83
  */
84
+ define('SUCURISCAN_PLUGIN_FOLDER', basename(dirname(__FILE__)));
85
 
86
  /**
87
  * The fullpath where the plugin's files will be located.
1853
  }
1854
 
1855
  if (is_array($tree) && !empty($tree)) {
1856
+ sort($tree); /* Sort in alphabetic order */
1857
+
1858
  return array_map(array('SucuriScan', 'fixPath'), $tree);
1859
  }
1860
  }
2173
  foreach ($dir_tree as $filepath) {
2174
  $dir_path = dirname($filepath);
2175
 
2176
+ if (!in_array($dir_path, $dirs)) {
2177
+ if (is_array($this->ignored_directories)
2178
+ && array_key_exists('directories', $this->ignored_directories)
2179
+ && is_array($this->ignored_directories['directories'])
2180
+ && in_array($dir_path, $this->ignored_directories['directories'])
2181
+ ) {
2182
+ continue;
2183
+ }
2184
+
2185
  $dirs[] = $dir_path;
2186
  }
2187
  }
3157
  * If the option is not in the external file nor in the database, and
3158
  * the name starts with the same prefix used by the plugin then we must
3159
  * return the default value defined by the author.
3160
+ *
3161
+ * Note that if the plain text file is not writable the function should
3162
+ * not delete the option from the database to keep backward compatibility
3163
+ * with previous installations of the plugin.
3164
  */
3165
  if (function_exists('get_option')) {
3166
  $value = get_option($option);
3167
 
3168
  if ($value !== false) {
3169
  if (strpos($option, 'sucuriscan_') === 0) {
3170
+ $written = self::update_option($option, $value);
3171
+
3172
+ if ($written === true) {
3173
+ delete_option($option);
3174
+ }
3175
  }
3176
 
3177
  return $value;
5094
  return substr($trail, 1);
5095
  }
5096
 
5097
+ private static function canCurlFollowRedirection()
5098
+ {
5099
+ $safe_mode = ini_get('safe_mode');
5100
+ $open_basedir = ini_get('open_basedir');
5101
+
5102
+ if ($safe_mode === '1' || $safe_mode === 'On') {
5103
+ return false;
5104
+ }
5105
+
5106
+ if (!empty($open_basedir)) {
5107
+ return false;
5108
+ }
5109
+
5110
+ return true;
5111
+ }
5112
+
5113
  /**
5114
  * Assign the communication protocol.
5115
  *
5332
  curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
5333
  curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $timeout);
5334
  curl_setopt($curl, CURLOPT_TIMEOUT, $timeout * 2);
5335
+
5336
+ if (self::canCurlFollowRedirection()) {
5337
+ curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
5338
+ curl_setopt($curl, CURLOPT_MAXREDIRS, 2);
5339
+ }
5340
 
5341
  if ($method === 'POST') {
5342
  curl_setopt($curl, CURLOPT_POST, true);
12581
  $blocked = $cache->getAll();
12582
  $cache_key = md5($username);
12583
 
12584
+ if (is_array($blocked)
12585
+ && is_string($cache_key)
12586
+ && array_key_exists($cache_key, $blocked)
12587
+ ) {
12588
  $blocked[$cache_key]->last_attempt = time();
12589
  $cache->set($cache_key, $blocked[$cache_key]);
12590
 
12652
  }
12653
 
12654
  if ($page_nonce) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12655
  // Enable or disable the filesystem scanner.
12656
  if ($fs_scanner = SucuriScanRequest::post(':fs_scanner', '(en|dis)able')) {
12657
  $action_d = $fs_scanner . 'd';
12924
  $display_manual_key_form = (bool) (SucuriScanRequest::post(':recover_key') !== false);
12925
 
12926
  if ($nonce) {
12927
+ if (!empty($_POST)) {
12928
+ $fpath = SucuriScanOption::optionsFilePath();
12929
+
12930
+ if (!is_writable($fpath)) {
12931
+ SucuriScanInterface::error(
12932
+ 'Storage is not writable: <code>'
12933
+ . $fpath . '</code>'
12934
+ );
12935
+ }
12936
+ }
12937
+
12938
+ // Remove API key from the local storage.
12939
+ if (SucuriScanRequest::post(':remove_api_key') !== false) {
12940
+ SucuriScanAPI::setPluginKey('');
12941
+ wp_clear_scheduled_hook('sucuriscan_scheduled_scan');
12942
+ SucuriScanEvent::report_critical_event('Sucuri API key was deleted.');
12943
+ SucuriScanEvent::notify_event('plugin_change', 'Sucuri API key removed');
12944
+ }
12945
+
12946
+ // Save API key after it was recovered by the administrator.
12947
+ if ($api_key = SucuriScanRequest::post(':manual_api_key')) {
12948
+ SucuriScanAPI::setPluginKey($api_key, true);
12949
+ SucuriScanEvent::schedule_task();
12950
+ SucuriScanEvent::report_info_event('Sucuri API key was added manually.');
12951
+ }
12952
+
12953
+ // Generate new API key from the API service.
12954
  if (SucuriScanRequest::post(':plugin_api_key') !== false) {
12955
  $user_id = SucuriScanRequest::post(':setup_user');
12956
  $user_obj = SucuriScan::get_user_by_id($user_id);
14807
  }
14808
  }
14809
 
14810
+ if (class_exists('WP_Rewrite')
14811
+ && is_string($rules)
14812
+ && !empty($rules)
14813
+ ) {
14814
  $rewrite = new WP_Rewrite();
14815
  $standard = $rewrite->mod_rewrite_rules();
14816
 
14817
+ if (!empty($standard)) {
14818
+ return (bool) (strpos($rules, $standard) !== false);
14819
+ }
14820
  }
14821
 
14822
  return false;