PluginProbe ʕ •ᴥ•ʔ
NinjaFirewall (WP Edition) – Advanced Security Plugin and Firewall / trunk
NinjaFirewall (WP Edition) – Advanced Security Plugin and Firewall vtrunk
4.9 4.8.8 4.8.7 4.8.6 trunk 4.5 4.5.1 4.5.10 4.5.11 4.5.2 4.5.3 4.5.4 4.5.5 4.5.6 4.5.7 4.5.8 4.5.9 4.6 4.6.1 4.7 4.7.1 4.7.2 4.7.3 4.7.4 4.7.5 4.8 4.8.1 4.8.2 4.8.3 4.8.4 4.8.5
ninjafirewall / lib / class-security-updates.php
ninjafirewall / lib Last commit date
share 9 years ago .htaccess 11 years ago anti_malware.php 5 years ago class-api.php 4 weeks ago class-centralised-logging.php 4 weeks ago class-coupon.php 7 months ago class-email-sodium.php 2 months ago class-firewall-log.php 4 weeks ago class-helpers.php 9 months ago class-import-export.php 5 months ago class-ip.php 5 months ago class-nfw-database.php 7 months ago class-plugin-upgrade.php 4 weeks ago class-security-updates.php 4 weeks ago class-session.php 4 weeks ago class_mail.php 2 months ago firewall.php 4 weeks ago fw_fileguard.php 5 months ago fw_livelog.php 1 year ago help.php 4 weeks ago helpers.php 4 weeks ago i18n-extra.php 4 weeks ago i18n.php 1 year ago index.html 13 years ago init_update.php 2 years ago install.php 1 year ago install_default.php 4 weeks ago loader.php 7 months ago mail_template_firewall.php 1 year ago mail_template_plugin.php 4 weeks ago scheduled_tasks.php 3 years ago settings_dashboard.php 4 weeks ago settings_dashboard_about.php 2 months ago settings_dashboard_statistics.php 2 months ago settings_event_notifications.php 4 weeks ago settings_events.php 2 months ago settings_firewall_options.php 2 months ago settings_firewall_policies.php 4 weeks ago settings_login_protection.php 2 months ago settings_logs.php 4 weeks ago settings_logs_firewall_log.php 4 weeks ago settings_logs_live_log.php 2 months ago settings_monitoring.php 2 months ago settings_monitoring_file_check.php 2 months ago settings_monitoring_file_guard.php 2 months ago settings_network.php 2 months ago settings_security_rules.php 2 months ago settings_security_rules_editor.php 4 weeks ago settings_security_rules_update.php 4 weeks ago sign.pub 7 years ago thickbox.php 4 years ago widget.php 3 years ago wpplus.php 5 months ago
class-security-updates.php
416 lines
1 <?php
2 /*
3 +=====================================================================+
4 | _ _ _ _ _____ _ _ _ |
5 | | \ | (_)_ __ (_) __ _| ___(_)_ __ _____ ____ _| | | |
6 | | \| | | '_ \ | |/ _` | |_ | | '__/ _ \ \ /\ / / _` | | | |
7 | | |\ | | | | || | (_| | _| | | | | __/\ V V / (_| | | | |
8 | |_| \_|_|_| |_|/ |\__,_|_| |_|_| \___| \_/\_/ \__,_|_|_| |
9 | |__/ |
10 | (c) NinTechNet Limited ~ https://nintechnet.com/ |
11 +=====================================================================+
12 */
13
14 if ( class_exists('NinjaFirewall_security_updates') ) {
15 return;
16 }
17
18
19 class NinjaFirewall_security_updates {
20
21 private static $found = [];
22 private static $list = [];
23 private static $transient_name = 'nfw_fetchsecupdates';
24 private static $transient_int = 10000;
25
26 private static $main_site_only = true;
27
28
29 /**
30 * Retrieve and check the security updates (WordPress, plugins and themes).
31 * Called by NinjaFirewall's garbage collector.
32 */
33 public static function check() {
34 /**
35 * We run on the main site only.
36 */
37 if ( self::$main_site_only && ! is_main_site() ) {
38 return;
39 }
40
41 if ( get_transient( self::$transient_name ) !== false ) {
42 return;
43 }
44
45 $nfw_checked = nfw_get_option('nfw_checked');
46 if ( empty( $nfw_checked ) ) {
47 $nfw_checked = [];
48 }
49
50 $nfw_options = nfw_get_option('nfw_options');
51 if ( empty( $nfw_options['secupdates'] ) ) {
52 // Option is disabled, exiting.
53 return;
54 }
55
56 /**
57 * Connect to the remove API.
58 */
59 require_once __DIR__ .'/class-api.php';
60 self::$list = NinjaFirewall_api::download_security_updates();
61
62 if (! isset( self::$list['wordpress'] ) ||
63 ! isset( self::$list['themes'] ) ||
64 ! isset( self::$list['plugins'] ) ) {
65
66 nfw_log_error( __('Downloaded list of vulnerabilities is corrupted', 'ninjafirewall') );
67 return false;
68 }
69
70 set_transient( self::$transient_name, 1, self::$transient_int );
71
72 /**
73 * Check WordPress security updates.
74 */
75 global $wp_version;
76 if ( isset( self::$list['wordpress']['version'] ) ) {
77
78 if ( version_compare( $wp_version, self::$list['wordpress']['version'], '<') &&
79 version_compare( $wp_version, self::$list['wordpress']['mini'], '>=') ) {
80 /**
81 * Make sure the user wasn't already warned about that.
82 */
83 if (! isset( $nfw_checked['wordpress']['version'] ) ||
84 version_compare( $nfw_checked['wordpress']['version'], self::$list['wordpress']['version'], '<') ) {
85
86 self::$found['wordpress']['cur_version'] = $wp_version;
87 self::$found['wordpress']['new_version'] = self::$list['wordpress']['version'];
88 self::$found['wordpress']['level'] = self::$list['wordpress']['level'];
89 }
90 }
91 /**
92 * Mark as checked.
93 */
94 $nfw_checked['wordpress']['version'] = self::$list['wordpress']['version'];
95 $nfw_checked['wordpress']['mini'] = self::$list['wordpress']['mini'];
96 }
97
98 /**
99 * Check themes security updates.
100 */
101 if ( ! function_exists('wp_get_themes') ) {
102 require_once ABSPATH .'wp-includes/theme.php';
103 }
104 $themes = wp_get_themes();
105
106 foreach( $themes as $k => $v ) {
107 /**
108 * No name or no version (unlike plugins, we're dealing with objects here).
109 */
110 if ( $v->Name == '' || $v->Version == '') {
111 continue;
112 }
113 $hash = hash('sha256', $k );
114 /**
115 * Check if the theme is installed.
116 */
117 if ( isset( self::$list['themes'][$hash] ) ) {
118
119 if ( version_compare( $v->Version, self::$list['themes'][$hash]['version'], '<') &&
120 version_compare( $v->Version, self::$list['themes'][$hash]['mini'], '>=') ) {
121 /**
122 * Make sure we didn't inform the user yet.
123 */
124 if (! isset( $nfw_checked['themes'][$k] ) ||
125 version_compare( $nfw_checked['themes'][$k]['version'], self::$list['themes'][$hash]['version'], '<') ) {
126
127 self::$found['themes'][$k]['name'] = $v->Name;
128 self::$found['themes'][$k]['cur_version'] = $v->Version;
129 self::$found['themes'][$k]['new_version'] = self::$list['themes'][$hash]['version'];
130 self::$found['themes'][$k]['level'] = self::$list['themes'][$hash]['level'];
131 }
132 }
133 /**
134 * Mark as checked.
135 */
136 $nfw_checked['themes'][$k]['version'] = self::$list['themes'][$hash]['version'];
137 $nfw_checked['themes'][$k]['mini'] = self::$list['themes'][$hash]['mini'];
138 }
139 }
140
141 /**
142 * Check plugins security updates.
143 */
144 if ( ! function_exists('get_plugins') ) {
145 require_once ABSPATH .'wp-admin/includes/plugin.php';
146 }
147 $plugins = get_plugins();
148
149 foreach( $plugins as $k => $v ) {
150 /**
151 * No name or no version (unlike themes, we're dealing with arrays here).
152 */
153 if ( empty( $v['Name'] ) || empty( $v['Version'] ) ) {
154 continue;
155 }
156 $hash = hash('sha256', $k );
157 /**
158 * Check if the plugin is installed.
159 */
160 if ( isset( self::$list['plugins'][$hash] ) ) {
161
162 if ( version_compare( $v['Version'], self::$list['plugins'][$hash]['version'], '<') &&
163 version_compare( $v['Version'], self::$list['plugins'][$hash]['mini'], '>=') ) {
164 /**
165 * Make sure we didn't inform the user yet.
166 */
167 if (! isset( $nfw_checked['plugins'][$k] ) ||
168 version_compare( $nfw_checked['plugins'][$k]['version'], self::$list['plugins'][$hash]['version'], '<') ) {
169 /**
170 * Add it to the notification list.
171 */
172 self::$found['plugins'][$k]['name'] = $v['Name'];
173 self::$found['plugins'][$k]['cur_version'] = $v['Version'];
174 self::$found['plugins'][$k]['new_version'] = self::$list['plugins'][$hash]['version'];
175 self::$found['plugins'][$k]['level'] = self::$list['plugins'][$hash]['level'];
176 }
177 }
178 /**
179 * Mark as checked.
180 */
181 $nfw_checked['plugins'][$k]['version'] = self::$list['plugins'][$hash]['version'];
182 $nfw_checked['plugins'][$k]['mini'] = self::$list['plugins'][$hash]['mini'];
183 }
184 }
185 /**
186 * Send a email notification to the user.
187 */
188 if (! empty( self::$found ) ) {
189 self::alert();
190 }
191
192 /**
193 * Always update the checked list.
194 */
195 nfw_update_option('nfw_checked', $nfw_checked, false );
196
197 return;
198 }
199
200
201 /**
202 * Send a notification to the user with the list of security updates available.
203 */
204 private static function alert() {
205
206 $message = '';
207 /**
208 * WordPress.
209 */
210 if (! empty( self::$found['wordpress'] ) ) {
211 $message .= "WordPress:\n" .
212 sprintf(
213 __('Your version: %s', 'ninjafirewall'), self::$found['wordpress']['cur_version']
214 ) ."\n".
215 sprintf(
216 __('New version: %s', 'ninjafirewall'), self::$found['wordpress']['new_version']
217 ) ."\n";
218 if ( self::$found['wordpress']['level'] == 2 ) {
219 $message .= __('Severity: This is an important security update', 'ninjafirewall') ."\n";
220 } elseif ( self::$found['wordpress']['level'] == 3 ) {
221 $message .= __('Severity: **This is a critical security update**', 'ninjafirewall') ."\n";
222 }
223 $message .= "\n";
224 }
225 /**
226 * Plugins.
227 */
228 if (! empty( self::$found['plugins'] ) ) {
229 foreach( self::$found['plugins'] as $k => $v ) {
230 $message .= sprintf(
231 __('Plugin: %s', 'ninjafirewall'), self::$found['plugins'][$k]['name']
232 ) ."\n".
233 sprintf(
234 __('Your version: %s', 'ninjafirewall'), self::$found['plugins'][$k]['cur_version']
235 ) ."\n".
236 sprintf(
237 __('New version: %s', 'ninjafirewall'), self::$found['plugins'][$k]['new_version']
238 ) ."\n";
239
240 if ( self::$found['plugins'][$k]['level'] == 2 ) {
241 $message .= __('Severity: This is an important security update', 'ninjafirewall') ."\n";
242 } elseif ( self::$found['plugins'][$k]['level'] == 3 ) {
243 $message .= __('Severity: **This is a critical security update**', 'ninjafirewall') ."\n";
244 }
245 $message .= "\n";
246 }
247 }
248 /**
249 * Themes.
250 */
251 if (! empty( self::$found['themes'] ) ) {
252
253 foreach( self::$found['themes'] as $k => $v ) {
254 $message .= sprintf(
255 __('Theme: %s', 'ninjafirewall'), self::$found['themes'][$k]['name']
256 ) ."\n".
257 sprintf(
258 __('Your version: %s', 'ninjafirewall'), self::$found['themes'][$k]['cur_version']
259 ) ."\n".
260 sprintf(
261 __('New version: %s', 'ninjafirewall'), self::$found['themes'][$k]['new_version']
262 ) ."\n";
263
264 if ( self::$found['themes'][$k]['level'] == 2 ) {
265 $message .= __('Severity: This is an important security update', 'ninjafirewall') ."\n";
266 } elseif ( self::$found['themes'][$k]['level'] == 3 ) {
267 $message .= __('Severity: **This is a critical security update**', 'ninjafirewall') ."\n";
268 }
269 $message .= "\n";
270 }
271 }
272 if ( is_multisite() ) {
273 $url = network_home_url('/');
274 } else {
275 $url = home_url('/');
276 }
277 /**
278 * Email notification.
279 */
280 $subject = [];
281 $content = [ ucfirst( date_i18n('F j, Y @ H:i:s T') ), $url, $message ];
282
283 NinjaFirewall_mail::send('security_updates', $subject, $content, '', [], 1 );
284 }
285
286
287 /**
288 * Display a red notice if there's a pending security update in the backend "Plugins" page.
289 */
290 public static function display() {
291 /**
292 * We run on the main site only.
293 */
294 if ( self::$main_site_only && ! is_main_site() ) {
295 return;
296 }
297
298 $nfw_checked = nfw_get_option('nfw_checked');
299 if ( empty( $nfw_checked['plugins'] ) ) {
300 return;
301 }
302
303 /**
304 * Check plugins updates.
305 */
306 if (! function_exists('get_plugins') ) {
307 require_once ABSPATH .'wp-admin/includes/plugin.php';
308 }
309
310 $plugins = get_plugins();
311 $cleared = 0;
312 // Get the list of plugin updates that WordPress marked as available.
313 $wp_updates = get_site_transient('update_plugins');
314
315 foreach( $plugins as $k => $v ) {
316 // No name or no version (unlike themes, we're dealing with arrays here)
317 if ( empty( $v['Name'] ) || empty( $v['Version'] ) ) {
318 continue;
319 }
320
321 if ( isset( $nfw_checked['plugins'][$k] ) ) {
322
323 if ( empty( $nfw_checked['plugins'][$k]['mini'] ) ) {
324 // Since version 4.9
325 $nfw_checked['plugins'][$k]['mini'] = 0;
326 }
327 /**
328 * Compare current and available versions.
329 */
330 if ( version_compare( $v['Version'], $nfw_checked['plugins'][$k]['version'], '<') &&
331 version_compare( $v['Version'], $nfw_checked['plugins'][$k]['mini'], '>=') ) {
332
333 $args = [
334 'name' => $v['Name'],
335 'plugin' => $k,
336 'version' => $nfw_checked['plugins'][$k]['version'],
337 'nonce' => wp_create_nonce('pluginupgrade'),
338 // We don't display the "Install now" button if WordPress allows the upgrade
339 'upgrade' => isset( $wp_updates->response[ $k ] ) ? false : true
340 ];
341
342 add_action( "after_plugin_row_{$k}",
343 function() use ( $args ) {
344 ?>
345 <tr class="plugin-update-tr active">
346 <td colspan="4" class="plugin-update colspanchange">
347 <div class="update-message notice inline notice-error notice-alt">
348 <?php
349 echo esc_html__('Important: NinjaFirewall has detected that this is a security update.', 'ninjafirewall') . ' '.
350 esc_html__("Don't leave your blog at risk, make sure to update as soon as possible.", 'ninjafirewall');
351 echo '<br />';
352 echo '<strong>'. esc_html__('Plugin:', 'ninjafirewall') .'</strong> <em>'.
353 esc_html( $args['name'] ) .'</em> - <strong>'. esc_html__('New version:', 'ninjafirewall') .'</strong> <em>'.
354 esc_html( $args['version'] ) .'</em>';
355
356 if ( $args['upgrade'] ) {
357 echo '<p>' . esc_html__('Because WordPress.org enforces a mandatory cooldown period of several hours on all new plugin releases, NinjaFirewall allows you to update this plugin immediately by clicking the button below.', 'ninjafirewall') .'</p>';
358 ?>
359 <button type="button" id="nf-progress-id" class="button button-secondary" onClick="nfwjs_upgrade_plugin('<?php
360 echo esc_attr( $args['plugin'] ) ?>','<?php
361 echo esc_attr( $args['version'] ) ?>','<?php
362 echo esc_attr( $args['nonce'] ) ?>')" />
363 <?php
364 echo esc_html__('Update the plugin now!', 'ninjafirewall' )?></button>
365 &nbsp;&nbsp;&nbsp;
366 <img style="vertical-align:middle;display:none" id="nf-progress-gif" src="<?php
367 echo plugins_url('/images/progress.gif', dirname (__FILE__ ) ) ?>" />
368 <?php
369 }
370 echo '<br/><a href="https://blog.nintechnet.com/how-to-get-informed-about-the-latest-security-updates-in-your-wordpress-plugins-and-themes/" target="_blank">' .
371 esc_html__('More info about this warning', 'ninjafirewall') .'</a>';
372 ?>
373 </div>
374 </td>
375 </tr>
376 <?php
377 }
378 );
379 } else {
380 // Remove if from our cache
381 unset( $nfw_checked['plugins'][$k] );
382 $cleared = 1;
383 }
384 }
385 }
386 /**
387 * Clear the list of plugins or themes that were uninstalled instead of updated.
388 */
389 if (! empty( $nfw_checked['plugins'] ) ) {
390 foreach( $nfw_checked['plugins'] as $k => $v ) {
391 if (! file_exists( WP_PLUGIN_DIR ."/$k" ) ) {
392 unset( $nfw_checked['plugins'][$k] );
393 $cleared = 1;
394 }
395 }
396 }
397 if (! empty( $nfw_checked['themes'] ) ) {
398 foreach( $nfw_checked['themes'] as $k => $v ) {
399 if (! is_dir( WP_CONTENT_DIR ."/themes/$k" ) ) {
400 unset( $nfw_checked['themes'][$k] );
401 $cleared = 1;
402 }
403 }
404 }
405 /**
406 * Update our list, if needed.
407 */
408 if ( $cleared ) {
409 nfw_update_option('nfw_checked', $nfw_checked, false );
410 }
411 }
412
413 }
414 // =====================================================================
415 // EOF
416