PluginProbe
Patchstack – WordPress & Plugins Security / 2.1.11
Patchstack – WordPress & Plugins Security v2.1.11
2.3.7 trunk 2.1.0 2.1.1 2.1.10 2.1.11 2.1.12 2.1.13 2.1.14 2.1.15 2.1.16 2.1.17 2.1.18 2.1.19 2.1.2 2.1.20 2.1.21 2.1.22 2.1.23 2.1.24 2.1.25 2.1.3 2.1.4 2.1.5 2.1.6 All 49 releases
← All changes | patchstack.php +39 -133 2.3.72.1.11 View file →
@@ -1,16 +1,15 @@
1 1 <?php
2 2 /**
3 3 * Plugin Name: Patchstack Security
4 - * Plugin URI: https://patchstack.com/?utm_medium=wp&utm_source=dashboard&utm_campaign=patchstack%20plugin
5 - * Author URI: https://patchstack.com/?utm_medium=wp&utm_source=dashboard&utm_campaign=patchstack%20plugin
4 + * Plugin URI: https://patchstack.com
6 5 * Description: Patchstack identifies security vulnerabilities in WordPress plugins, themes, and core.
7 - * Version: 2.3.7
6 + * Version: 2.1.11
8 7 * Author: Patchstack
9 8 * License: GPLv3
10 9 * Text Domain: patchstack
11 10 * Domain Path: /languages
12 - * Requires at least: 5.2
11 + * Requires at least: 4.4
13 12 * Requires PHP: 5.6
14 13 */
15 14
16 15 // Do not allow the file to be called directly.
@@ -33,9 +32,9 @@
33 32
34 33 // Set up our filename.
35 34 $file_name = strtolower( str_replace( '_', '-', substr( $class_name, strlen( 'P_' ) ) ) );
36 35 $dir = trailingslashit( dirname( __FILE__ ) ) . 'includes/';
37 - $target = [ $dir . $file_name . '.php', $dir . 'admin/' . str_replace( 'admin-', '', $file_name ) . '.php' ];
36 + $target = array( $dir . $file_name . '.php', $dir . 'admin/' . str_replace( 'admin-', '', $file_name ) . '.php' );
38 37
39 38 // Attempt each target and load if it exists.
40 39 foreach ( $target as $file ) {
41 40 if ( file_exists( $file ) ) {
@@ -58,9 +57,9 @@
58 57 * The plugin version.
59 58 *
60 59 * @var string
61 60 */
62 - const VERSION = '2.3.7';
61 + const VERSION = '2.1.11';
63 62
64 63 /**
65 64 * API URL of Patchstack to communicate with.
66 65 *
@@ -89,8 +88,15 @@
89 88 */
90 89 const PRIVATE_KEY = 'PATCHSTACK_PRIVATE_KEY';
91 90
92 91 /**
92 + * Known IP addresses.
93 + *
94 + * @var array
95 + */
96 + protected $ips = array( '18.221.197.243', '52.15.237.250', '3.19.3.34', '3.18.238.17', '13.58.49.77', '18.222.191.77', '3.131.108.250', '3.23.157.140', '18.220.70.233', '3.140.84.221', '185.212.171.100' );
97 +
98 + /**
93 99 * URL of the plugin directory.
94 100 *
95 101 * @var string
96 102 */
@@ -114,9 +120,9 @@
114 120 * Detailed activation error messages.
115 121 *
116 122 * @var array
117 123 */
118 - protected $activation_errors = [];
124 + protected $activation_errors = array();
119 125
120 126 /**
121 127 * Singleton instance of plugin.
122 128 *
@@ -139,12 +145,12 @@
139 145 protected $htaccess;
140 146 protected $hacker_log;
141 147 protected $upload;
142 148 protected $rules;
143 - protected $hide_login;
144 149 protected $listener;
145 150 protected $event_log;
146 151 protected $multisite;
152 + protected $notice;
147 153 protected $admin_ajax;
148 154 protected $admin_general;
149 155 protected $admin_menu;
150 156 protected $admin_options;
@@ -169,15 +175,8 @@
169 175 $this->basename = plugin_basename( __FILE__ );
170 176 $this->url = plugin_dir_url( __FILE__ );
171 177 $names = explode( '/', $this->basename );
172 178 $this->name = $names[0];
173 -
174 - // Define WP_CLI command.
175 - if ( defined( 'WP_CLI' ) && WP_CLI && method_exists('\WP_CLI', 'add_command')) {
176 - \WP_CLI::add_command( 'patchstack activate', [ $this, 'cli_activate' ] );
177 - \WP_CLI::add_command( 'patchstack deactivate', [ $this, 'cli_deactivate' ] );
178 - \WP_CLI::add_command( 'patchstack status', [ $this, 'cli_status' ] );
179 - }
180 179 }
181 180
182 181 /**
183 182 * Call the constructor of all the Patchstack related classes.
@@ -185,9 +184,9 @@
185 184 * @return void
186 185 */
187 186 public function plugin_classes() {
188 187 // Define the array of the classes.
189 - foreach ( [
188 + foreach ( array(
190 189 'admin_options' => 'P_Admin_Options',
191 190 'cron' => 'P_Cron',
192 191 'api' => 'P_Api',
193 192 'login' => 'P_Login',
@@ -196,21 +195,20 @@
196 195 'htaccess' => 'P_Htaccess',
197 196 'hacker_log' => 'P_Hacker_Log',
198 197 'upload' => 'P_Upload',
199 198 'rules' => 'P_Rules',
200 - 'hide_login' => 'P_Hide_Login',
199 + 'listener' => 'P_Listener',
201 200 'event_log' => 'P_Event_Log',
202 201 'activation' => 'P_Activation',
203 - 'listener' => 'P_Listener',
204 202 'multisite' => 'P_Multisite',
203 + 'notice' => 'P_Cookie_Notice',
205 204 'admin_ajax' => 'P_Admin_Ajax',
206 205 'admin_general' => 'P_Admin_General',
207 206 'admin_menu' => 'P_Admin_Menu',
208 - ] as $var => $class ) {
207 + ) as $var => $class ) {
209 208 $this->$var = new $class( $this );
210 209 }
211 210
212 - // Load firewall base functionality.
213 211 $this->firewall_base = new P_Firewall( true, $this, true );
214 212 }
215 213
216 214 /**
@@ -223,86 +221,8 @@
223 221 $this->activation->activate( $this );
224 222 }
225 223
226 224 /**
227 - * Connects the Patchstack plugin to the API with the license id and secret key.
228 - *
229 - * Returns an error if the connection was not successful.
230 - *
231 - * ## OPTIONS
232 - *
233 - * [<id>]
234 - * : The API client id.
235 - *
236 - * [<secret>]
237 - * : The API secret key.
238 - *
239 - * <secret-id>
240 - * : The API client id and secret key merged together, found in the App. E.g. 2b072e8b60402e30d481df351fc08183906254e0-123456
241 - *
242 - * ## EXAMPLES
243 - *
244 - * $ wp patchstack activate 123456 2b072e8b60402e30d481df351fc08183906254e0
245 - * Success: The Patchstack plugin has been successfully connected.
246 - *
247 - * or
248 - *
249 - * $ wp patchstack activate 2b072e8b60402e30d481df351fc08183906254e0-123456
250 - * Success: The Patchstack plugin has been successfully connected.
251 - */
252 - public function cli_activate( $args ) {
253 - // Handle both ways to activate the plugin.
254 - if ( count( $args ) === 1 && strpos( $args[0], '-' ) !== false ) {
255 - list( $secret, $id ) = explode( '-', $args[0] );
256 - } else {
257 - $id = isset( $args[0] ) ? trim( $args[0] ) : '';
258 - $secret = isset( $args[1] ) ? trim( $args[1] ) : '';
259 - }
260 -
261 - $result = $this->activation->alter_license( $id, $secret, 'activate' );
262 - if ( $result['result'] == 'error' ) {
263 - \WP_CLI::error( "The Patchstack plugin could not be connected. Make sure the id and secret key are valid and that api.patchstack.com is not blocked. Additional information:\n" . $result['body'] );
264 - return;
265 - }
266 -
267 - \WP_CLI::success( 'The Patchstack plugin has been successfully connected.' );
268 - }
269 -
270 - /**
271 - * Disconnects the Patchstack plugin from the API and removes the API key.
272 - *
273 - * ## EXAMPLES
274 - *
275 - * $ wp patchstack deactivate
276 - * Success: The Patchstack plugin has been successfully disconnected.
277 - */
278 - public function cli_deactivate() {
279 - $this->activation->deactivate();
280 - $this->activation->alter_license( '', '', 'deactivate' );
281 -
282 - \WP_CLI::success( 'The Patchstack plugin has been successfully disconnected.' );
283 - }
284 -
285 - /**
286 - * Gets the current API connection status from the Patchstack plugin.
287 - *
288 - * ## EXAMPLES
289 - *
290 - * $ wp patchstack status
291 - * Success: The Patchstack plugin is currently connected to the API.
292 - *
293 - * $ wp patchstack status
294 - * Warning: The Patchstack plugin is not connected to the API.
295 - */
296 - public function cli_status() {
297 - if ( $this->api->is_connected() ) {
298 - \WP_CLI::success( __( 'The Patchstack plugin is currently connected to the API.', 'patchstack' ) );
299 - } else {
300 - \WP_CLI::warning( __( 'The Patchstack plugin is not connected to the API.', 'patchstack' ) );
301 - }
302 - }
303 -
304 - /**
305 225 * Deactivate the plugin.
306 226 *
307 227 * @return void
308 228 */
@@ -311,23 +231,24 @@
311 231 $this->activation->deactivate();
312 232 }
313 233
314 234 /**
315 - * Load translated strings for the plugin.
235 + * Boot Patchstack and its classes.
316 236 *
317 237 * @return void
318 238 */
319 - public function load_textdomain () {
320 - load_plugin_textdomain( 'patchstack', false, dirname( $this->basename ) . '/languages/' );
239 + public function hooks() {
240 + add_action( 'init', array( $this, 'init' ), ~PHP_INT_MAX );
321 241 }
322 242
323 243 /**
324 - * Boot Patchstack.
244 + * Boot Patchstack
325 245 *
326 246 * @return void
327 247 */
328 248 public function init() {
329 - add_action( 'init', [ $this, 'load_textdomain' ] );
249 + // Load translated strings for plugin.
250 + load_plugin_textdomain( 'patchstack', false, dirname( $this->basename ) . '/languages/' );
330 251
331 252 // Initialize plugin classes.
332 253 $this->plugin_classes();
333 254
@@ -338,9 +259,9 @@
338 259 if ( get_option( 'patchstack_api_token', '' ) == '' && get_option( 'patchstack_license_expiry', '' ) == '' ) {
339 260 $this->api->update_license_status();
340 261 }
341 262
342 - // Run firewall if not disabled and license activated.
263 + // Determine if the license is activated and not expired.
343 264 if ( get_option( 'patchstack_license_activated', 0 ) == 1 && get_option( 'patchstack_basic_firewall', 0 ) == 1 && get_option( 'patchstack_license_free', 0 ) == 0 ) {
344 265 $this->firewall = new P_Firewall( true, $this );
345 266 }
346 267 }
@@ -395,35 +316,22 @@
395 316 * @return void
396 317 */
397 318 function patchstack_uninstall() {
398 319 // Delete most of the Patchstack options.
399 - global $wpdb;
400 - $options = $wpdb->get_results( "SELECT option_name FROM $wpdb->options WHERE option_name LIKE 'patchstack_%'" );
320 + $options = array( 'patchstack_eventlog_lastid', 'patchstack_api_token', 'patchstack_dashboardlock', 'patchstack_pluginedit', 'patchstack_move_logs', 'patchstack_userenum', 'patchstack_basicscanblock', 'patchstack_hidewpcontent', 'patchstack_hidewpversionk', 'patchstack_prevent_default_file_access', 'patchstack_basic_firewall', 'patchstack_known_blacklist', 'patchstack_block_debug_log_access', 'patchstack_block_fake_bots', 'patchstack_index_views', 'patchstack_proxy_comment_posting', 'patchstack_bad_query_strings', 'patchstack_advanced_character_string_filter', 'patchstack_advanced_blacklist_firewall', 'patchstack_forbid_rfi', 'patchstack_image_hotlinking', 'patchstack_add_security_headers', 'patchstack_firewall_log_lastid', 'patchstack_user_log_lastid', 'patchstack_captcha_public_key', 'patchstack_captcha_private_key', 'patchstack_scan_interval', 'patchstack_scan_day', 'patchstack_scan_time', 'patchstack_hackers_log', 'patchstack_users_log', 'patchstack_visitors_log', 'external_updates-webarx', 'patchstack_wp_stats', 'patchstack_captcha_login_form', 'patchstack_license_activated', 'patchstack_license_expiry', 'patchstack_software_data_hash', 'patchstack_mv_wp_login', 'patchstack_rename_wp_login', 'patchstack_googledrive_backup_is_running', 'patchstack_googledrive_upload_state', 'patchstack_googledrive_access_token', 'patchstack_googledrive_refresh_token', 'patchstack_cron_offset', 'patchstack_htaccess_rules_hash' );
321 + foreach ( $options as $option ) {
322 + delete_option( $option );
401 323
402 - // Few options we want to keep.
403 - $keep = ['patchstack_hits_last_30', 'patchstack_hits_all_time', 'patchstack_clientid', 'patchstack_secretkey', 'patchstack_secretkey_nonce', 'patchstack_api_token'];
404 -
405 - // Delete everything else.
406 - foreach( $options as $option ) {
407 - if ( in_array( $option->option_name, $keep ) || stripos( $option->option_name, 'patchstack_captcha_' ) !== false ) {
408 - continue;
409 - }
410 -
411 - delete_option( $option->option_name );
412 -
413 324 if ( is_multisite() ) {
414 - delete_site_option( $option->option_name );
325 + delete_site_option( $option );
415 326 }
416 327 }
417 328
418 - // Drop all tables.
329 + // Drop all Patchstack tables.
419 330 global $wpdb;
420 - $prefixes = ['patchstack_', 'webarx_'];
421 - foreach ( $prefixes as $prefix ) {
422 - $tables = [ 'user_log', 'visitor_log', 'firewall_log', 'file_hashes', 'logic', 'ip', 'event_log' ];
423 - foreach ( $tables as $table ) {
424 - $wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . $prefix . $table );
425 - }
331 + $tables = array( 'patchstack_user_log', 'patchstack_visitor_log', 'patchstack_firewall_log', 'patchstack_file_hashes', 'patchstack_logic', 'patchstack_ip', 'patchstack_event_log' );
332 + foreach ( $tables as $table ) {
333 + $wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . $table );
426 334 }
427 335 }
428 336 }
429 337
@@ -437,13 +345,11 @@
437 345 return patchstack::get_instance();
438 346 }
439 347 }
440 348
441 -if ( ! has_action( 'plugins_loaded', [ patchstack(), 'init' ] ) ) {
442 - // Kick it off.
443 - add_action( 'plugins_loaded', [ patchstack(), 'init' ] );
349 +// Kick it off.
350 +add_action( 'plugins_loaded', array( patchstack(), 'hooks' ) );
444 351
445 - // Activation and deactivation hooks.
446 - register_activation_hook( __FILE__, [ patchstack(), 'activate' ] );
447 - register_deactivation_hook( __FILE__, [ patchstack(), 'deactivate' ] );
448 - register_uninstall_hook( __FILE__, 'patchstack_uninstall' );
449 -}
352 +// Activation and deactivation hooks.
353 +register_activation_hook( __FILE__, array( patchstack(), 'activate' ) );
354 +register_deactivation_hook( __FILE__, array( patchstack(), 'deactivate' ) );
355 +register_uninstall_hook( __FILE__, 'patchstack_uninstall' );