PluginProbe
Patchstack – WordPress & Plugins Security / 2.1.4
Patchstack – WordPress & Plugins Security v2.1.4
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 -131 trunk2.1.4 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.4
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.4';
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 *
@@ -143,8 +149,9 @@
143 149 protected $hide_login;
144 150 protected $listener;
145 151 protected $event_log;
146 152 protected $multisite;
153 + protected $notice;
147 154 protected $admin_ajax;
148 155 protected $admin_general;
149 156 protected $admin_menu;
150 157 protected $admin_options;
@@ -169,15 +176,8 @@
169 176 $this->basename = plugin_basename( __FILE__ );
170 177 $this->url = plugin_dir_url( __FILE__ );
171 178 $names = explode( '/', $this->basename );
172 179 $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 180 }
181 181
182 182 /**
183 183 * Call the constructor of all the Patchstack related classes.
@@ -185,9 +185,9 @@
185 185 * @return void
186 186 */
187 187 public function plugin_classes() {
188 188 // Define the array of the classes.
189 - foreach ( [
189 + foreach ( array(
190 190 'admin_options' => 'P_Admin_Options',
191 191 'cron' => 'P_Cron',
192 192 'api' => 'P_Api',
193 193 'login' => 'P_Login',
@@ -197,20 +197,20 @@
197 197 'hacker_log' => 'P_Hacker_Log',
198 198 'upload' => 'P_Upload',
199 199 'rules' => 'P_Rules',
200 200 'hide_login' => 'P_Hide_Login',
201 + 'listener' => 'P_Listener',
201 202 'event_log' => 'P_Event_Log',
202 203 'activation' => 'P_Activation',
203 - 'listener' => 'P_Listener',
204 204 'multisite' => 'P_Multisite',
205 + 'notice' => 'P_Cookie_Notice',
205 206 'admin_ajax' => 'P_Admin_Ajax',
206 207 'admin_general' => 'P_Admin_General',
207 208 'admin_menu' => 'P_Admin_Menu',
208 - ] as $var => $class ) {
209 + ) as $var => $class ) {
209 210 $this->$var = new $class( $this );
210 211 }
211 212
212 - // Load firewall base functionality.
213 213 $this->firewall_base = new P_Firewall( true, $this, true );
214 214 }
215 215
216 216 /**
@@ -223,86 +223,8 @@
223 223 $this->activation->activate( $this );
224 224 }
225 225
226 226 /**
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 227 * Deactivate the plugin.
306 228 *
307 229 * @return void
308 230 */
@@ -311,23 +233,24 @@
311 233 $this->activation->deactivate();
312 234 }
313 235
314 236 /**
315 - * Load translated strings for the plugin.
237 + * Boot Patchstack and its classes.
316 238 *
317 239 * @return void
318 240 */
319 - public function load_textdomain () {
320 - load_plugin_textdomain( 'patchstack', false, dirname( $this->basename ) . '/languages/' );
241 + public function hooks() {
242 + add_action( 'init', array( $this, 'init' ), ~PHP_INT_MAX );
321 243 }
322 244
323 245 /**
324 - * Boot Patchstack.
246 + * Boot Patchstack
325 247 *
326 248 * @return void
327 249 */
328 250 public function init() {
329 - add_action( 'init', [ $this, 'load_textdomain' ] );
251 + // Load translated strings for plugin.
252 + load_plugin_textdomain( 'patchstack', false, dirname( $this->basename ) . '/languages/' );
330 253
331 254 // Initialize plugin classes.
332 255 $this->plugin_classes();
333 256
@@ -338,9 +261,9 @@
338 261 if ( get_option( 'patchstack_api_token', '' ) == '' && get_option( 'patchstack_license_expiry', '' ) == '' ) {
339 262 $this->api->update_license_status();
340 263 }
341 264
342 - // Run firewall if not disabled and license activated.
265 + // Determine if the license is activated and not expired.
343 266 if ( get_option( 'patchstack_license_activated', 0 ) == 1 && get_option( 'patchstack_basic_firewall', 0 ) == 1 && get_option( 'patchstack_license_free', 0 ) == 0 ) {
344 267 $this->firewall = new P_Firewall( true, $this );
345 268 }
346 269 }
@@ -395,35 +318,22 @@
395 318 * @return void
396 319 */
397 320 function patchstack_uninstall() {
398 321 // 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_%'" );
322 + $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' );
323 + foreach ( $options as $option ) {
324 + delete_option( $option );
401 325
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 326 if ( is_multisite() ) {
414 - delete_site_option( $option->option_name );
327 + delete_site_option( $option );
415 328 }
416 329 }
417 330
418 - // Drop all tables.
331 + // Drop all Patchstack tables.
419 332 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 - }
333 + $tables = array( 'patchstack_user_log', 'patchstack_visitor_log', 'patchstack_firewall_log', 'patchstack_file_hashes', 'patchstack_logic', 'patchstack_ip', 'patchstack_event_log' );
334 + foreach ( $tables as $table ) {
335 + $wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . $table );
426 336 }
427 337 }
428 338 }
429 339
@@ -437,13 +347,11 @@
437 347 return patchstack::get_instance();
438 348 }
439 349 }
440 350
441 -if ( ! has_action( 'plugins_loaded', [ patchstack(), 'init' ] ) ) {
442 - // Kick it off.
443 - add_action( 'plugins_loaded', [ patchstack(), 'init' ] );
351 +// Kick it off.
352 +add_action( 'plugins_loaded', array( patchstack(), 'hooks' ) );
444 353
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 -}
354 +// Activation and deactivation hooks.
355 +register_activation_hook( __FILE__, array( patchstack(), 'activate' ) );
356 +register_deactivation_hook( __FILE__, array( patchstack(), 'deactivate' ) );
357 +register_uninstall_hook( __FILE__, 'patchstack_uninstall' );