PluginProbe
Patchstack – WordPress & Plugins Security / 2.2.8
Patchstack – WordPress & Plugins Security v2.2.8
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 | includes/upload.php +66 -29 2.1.52.2.8 View file →
@@ -25,17 +25,18 @@
25 25 $this->upload_software();
26 26 }
27 27
28 28 // Register the actions.
29 - add_action( 'patchstack_send_software_data', array( $this, 'upload_software' ) );
30 - add_action( 'patchstack_send_hacker_logs', array( $this, 'upload_firewall_logs' ) );
31 - add_action( 'patchstack_send_event_logs', array( $this, 'upload_activity_logs' ) );
29 + add_action( 'patchstack_send_software_data', [ $this, 'upload_software' ] );
30 + add_action( 'patchstack_send_hacker_logs', [ $this, 'upload_firewall_logs' ] );
31 + add_action( 'patchstack_send_event_logs', [ $this, 'upload_activity_logs' ] );
32 32
33 33 // In case a plugin or upgrade has been performed, re-synchronize with the app.
34 - add_action( 'activated_plugin', array( $this, 'upload_software' ) );
35 - add_action( 'deactivated_plugin', array( $this, 'upload_software' ) );
36 - add_action( 'upgrader_process_complete', array( $this, 'upload_software' ) );
37 - add_action( '_core_updated_successfully', array( &$this, 'upload_software' ) );
34 + add_action( 'activated_plugin', [ $this, 'upload_software' ] );
35 + add_action( 'deactivated_plugin', [ $this, 'upload_software' ] );
36 + add_action( 'deleted_plugin', [ $this, 'upload_software' ] );
37 + add_action( 'upgrader_process_complete', [ $this, 'upload_software' ] );
38 + add_action( '_core_updated_successfully', [ &$this, 'upload_software' ] );
38 39 }
39 40
40 41 /**
41 42 * Synchronize the software data with our API.
@@ -46,14 +47,16 @@
46 47 public function upload_software() {
47 48 // Get the software data and hash.
48 49 $data = $this->get_software_data();
49 50 $hash = sha1( json_encode( $data ) );
50 - if ( ! isset( $_POST['webarx_secret'] ) && get_option( 'patchstack_software_data_hash', false ) === $hash ) {
51 +
52 + // Do not sync for no reason.
53 + if ( ! defined( 'DOING_CRON' ) && ! isset( $_POST['webarx_secret'] ) && get_option( 'patchstack_software_data_hash', false ) === $hash && ! is_admin() ) {
51 54 return;
52 55 }
53 56
54 57 // Synchronize the software list with the API.
55 - $results = $this->plugin->api->upload_software( array( 'software' => json_encode( $data ) ) );
58 + $results = $this->plugin->api->upload_software( [ 'software' => json_encode( $data ) ] );
56 59 if ( isset( $results['success'] ) ) {
57 60 update_option( 'patchstack_software_data_hash', $hash );
58 61
59 62 // The result will also contain a list of all vulnerable plugins on the site that is returned by the API.
@@ -58,13 +61,28 @@
58 61
59 62 // The result will also contain a list of all vulnerable plugins on the site that is returned by the API.
60 63 // If the auto update setting is enabled for vulnerable plugins, perform the update once the 15 minute
61 64 // scheduled task "patchstack_update_plugins" is executed.
62 - $update = get_site_option( 'patchstack_auto_update', array() );
65 + $update = get_site_option( 'patchstack_auto_update', [] );
63 66 if ( isset( $results['vulnerable'] ) && is_array( $update ) && in_array( 'vulnerable', $update ) ) {
64 67 update_site_option( 'patchstack_vulnerable_plugins', $results['vulnerable'] );
65 68 }
66 69
70 + // If we have vulnerable plugins, determine if we had them before and if not, pull latest firewall rules.
71 + if ( isset( $results['vulnerable'] ) && count( $results['vulnerable'] ) > 0 ) {
72 + $prev = get_site_option( 'patchstack_latest_vulnerable', [] );
73 + foreach ( $results['vulnerable'] as $vuln ) {
74 + if ( ! in_array ( $vuln, $prev ) ) {
75 + do_action( 'patchstack_post_dynamic_firewall_rules' );
76 + break;
77 + }
78 + }
79 +
80 + update_site_option( 'patchstack_latest_vulnerable', $results['vulnerable'] );
81 + } else {
82 + update_site_option( 'patchstack_latest_vulnerable', [] );
83 + }
84 +
67 85 return $results;
68 86 }
69 87
70 88 return;
@@ -76,9 +94,9 @@
76 94 * @return void
77 95 */
78 96 public function upload_firewall_logs() {
79 97 global $wpdb;
80 - $lastid = get_option( 'patchstack_firewall_log_lastid', 0, true );
98 + $lastid = get_option( 'patchstack_firewall_log_lastid', 0 );
81 99 $items = $wpdb->get_results( $wpdb->prepare( 'SELECT ip, log_date, request_uri, user_agent, fid, method, post_data FROM ' . $wpdb->prefix . 'patchstack_firewall_log WHERE id > %d ORDER BY id', $lastid ) );
82 100
83 101 // No need to synchronize if there are no new logs present.
84 102 if ( $wpdb->num_rows == 0 ) {
@@ -85,9 +103,9 @@
85 103 return;
86 104 }
87 105
88 106 // Construct the array to be uploaded to our API.
89 - $logs = array();
107 + $logs = [];
90 108 foreach ( $items as $item ) {
91 109
92 110 // Entries that we don't want to store on the API side.
93 111 if ( stripos( $item->request_uri, 'wp-comments-post' ) !== false ) {
@@ -94,9 +112,9 @@
94 112 continue;
95 113 }
96 114
97 115 // Push to entries to be uploaded.
98 - $logs[] = array(
116 + $logs[] = [
99 117 'ip' => $item->ip,
100 118 'fid' => $item->fid,
101 119 'request_uri' => $item->request_uri,
102 120 'user_agent' => $item->user_agent,
@@ -102,18 +120,18 @@
102 120 'user_agent' => $item->user_agent,
103 121 'method' => $item->method,
104 122 'log_date' => $item->log_date,
105 123 'post_data' => $item->post_data,
106 - );
124 + ];
107 125 }
108 126
109 127 // JSON encode the logs and upload.
110 128 $logs = json_encode( $logs );
111 129 $results = $this->plugin->api->upload_firewall_logs(
112 - array(
130 + [
113 131 'logs' => $logs,
114 132 'type' => 'firewall',
115 - )
133 + ]
116 134 );
117 135 if ( isset( $results['errors'] ) ) {
118 136 return;
119 137 }
@@ -141,9 +159,9 @@
141 159 }
142 160
143 161 // Do we have data to upload?
144 162 $lastid = get_option( 'patchstack_eventlog_lastid', 0 );
145 - $items = $wpdb->get_results( $wpdb->prepare( 'SELECT author, ip, object, object_id, object_name, action, date FROM ' . $wpdb->prefix . 'patchstack_event_log WHERE id > %d' . $where . 'ORDER BY id', array( $lastid ) ) );
163 + $items = $wpdb->get_results( $wpdb->prepare( 'SELECT author, ip, object, object_id, object_name, action, date FROM ' . $wpdb->prefix . 'patchstack_event_log WHERE id > %d' . $where . 'ORDER BY id', [ $lastid ] ) );
146 164 if ( $wpdb->num_rows == 0 ) {
147 165 return;
148 166 }
149 167
@@ -148,9 +166,9 @@
148 166 }
149 167
150 168 // Send to the API.
151 169 $logs = json_encode( $items );
152 - $results = $this->plugin->api->upload_activity_logs( array( 'logs' => $logs ) );
170 + $results = $this->plugin->api->upload_activity_logs( [ 'logs' => $logs ] );
153 171 if ( isset( $results['errors'] ) ) {
154 172 return;
155 173 }
156 174
@@ -186,9 +204,9 @@
186 204 // Fetch list of plugins.
187 205 $all_plugin = get_plugins();
188 206 $installed_plugins = array_keys( $all_plugin );
189 207 $updatable_plugins = get_plugin_updates();
190 - $software_list = array();
208 + $software_list = [];
191 209
192 210 foreach ( $installed_plugins as $plugin ) {
193 211 if ( ! file_exists( WP_PLUGIN_DIR . '/' . $plugin ) ) {
194 212 continue;
@@ -199,16 +217,24 @@
199 217 $plugin_name = empty( $plugin_data['Name'] ) ? '' : $plugin_data['Name'];
200 218 $plugin_version = empty( $plugin_data['Version'] ) ? '' : $plugin_data['Version'];
201 219
202 220 if ( ! empty( $plugin_name ) && ! empty( $plugin_version ) ) {
203 - $software_list[] = array(
221 +
222 + // Determine the active state.
223 + if ( isset( $_GET['action'], $_GET['plugin'] ) && $_GET['action'] == 'deactivate' && $_GET['plugin'] == $plugin) {
224 + $active = 0;
225 + } else {
226 + $active = (int) is_plugin_active( $plugin );
227 + }
228 +
229 + $software_list[] = [
204 230 'sw_type' => 'plugin',
205 231 'sw_name' => $plugin_name,
206 232 'sw_cur_ver' => $plugin_version,
207 233 'sw_new_ver' => $new_version,
208 234 'sw_key' => $plugin,
209 - 'sw_active' => is_plugin_active( $plugin ),
210 - );
235 + 'sw_active' => $active
236 + ];
211 237 }
212 238 }
213 239
214 240 // Fetch list of themes.
@@ -223,15 +249,15 @@
223 249 $theme_name = $themes_data->get( 'Name' );
224 250 $theme_version = $themes_data->get( 'Version' );
225 251
226 252 if ( ! empty( $theme_name ) && ! empty( $theme_version ) ) {
227 - $software_list[] = array(
253 + $software_list[] = [
228 254 'sw_type' => 'theme',
229 255 'sw_name' => $theme_name,
230 256 'sw_cur_ver' => $theme_version,
231 257 'sw_new_ver' => $theme_new_version,
232 258 'sw_key' => $theme_key,
233 - );
259 + ];
234 260 }
235 261 }
236 262
237 263 // Fetch WordPress version.
@@ -237,22 +263,33 @@
237 263 // Fetch WordPress version.
238 264 global $wp_version;
239 265 $core_updates = get_core_updates();
240 266 $new_wp_version = ( ! empty( $core_updates ) && $core_updates[0]->response == 'upgrade' ) ? $core_updates[0]->version : '';
241 - $software_list[] = array(
267 + $software_list[] = [
242 268 'sw_type' => 'wordpress',
243 269 'sw_name' => 'WordPress',
244 270 'sw_cur_ver' => $wp_version,
245 271 'sw_new_ver' => $new_wp_version,
246 - );
272 + ];
247 273
248 274 // Fetch PHP version.
249 - $software_list[] = array(
275 + $software_list[] = [
250 276 'sw_type' => 'php',
251 277 'sw_name' => 'PHP',
252 - 'sw_cur_ver' => substr( phpversion(), 0, 5 ),
278 + 'sw_cur_ver' => phpversion(),
253 279 'sw_new_ver' => '',
254 - );
280 + ];
281 +
282 + // Fetch database server version.
283 + global $wpdb;
284 + if ( ! is_null( $wpdb ) ) {
285 + $software_list[] = [
286 + 'sw_type' => 'database',
287 + 'sw_name' => 'Database',
288 + 'sw_cur_ver' => $wpdb->get_var( 'SELECT VERSION()' ),
289 + 'sw_new_ver' => ''
290 + ];
291 + }
255 292
256 293 return $software_list;
257 294 }
258 295 }