PluginProbe
WPVulnerability / 4.3.0
WPVulnerability v4.3.0
5.1.6 5.1.2 5.1.1 5.0.1 5.0.0 trunk 0.1 0.2 1.0 1.0.1 1.1 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.3.0 1.3.1 1.3.2 1.3.3 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 All 57 releases
wpvulnerability / wpvulnerability-core.php

wpvulnerability-core.php in WPVulnerability 4.3.0, at wpvulnerability-core.php

217 lines 7.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Core functions
4 *
5 * @package WPVulnerability
6 *
7 * @version 2.0.0
8 */
9
10 defined( 'ABSPATH' ) || die( 'No script kiddies please!' );
11
12 /**
13 * Adds a vulnerability notice under vulnerable core.
14 *
15 * @since 2.0.0
16 *
17 * @return void
18 */
19 function wpvulnerability_core_info_after() {
20
21 // Retrieve the vulnerabilities for core from the options table and decode the JSON.
22 if ( is_multisite() ) {
23 $core_vulnerabilities = json_decode( get_site_option( 'wpvulnerability-core' ), true );
24 } else {
25 $core_vulnerabilities = json_decode( get_option( 'wpvulnerability-core' ), true );
26 }
27
28 // Generate the vulnerability notice message.
29 $message = sprintf(
30 /* translators: 1: core version */
31 __( 'WordPress %1$s has a known vulnerability that may be affecting this version.', 'wpvulnerability' ),
32 get_bloginfo( 'version' )
33 );
34
35 $information = '<p class="text-red"><img src="' . esc_url( WPVULNERABILITY_PLUGIN_URL ) . 'assets/icon.svg" style="height: 16px; vertical-align: text-top; width: 16px;" alt="" title="WPVulnerability"> <strong>' . $message . '</strong></p>';
36 $information .= '<table class="wp-list-table widefat wpvulnerability">';
37
38 // Loop through all vulnerabilities for the current version and add their details to the table row HTML markup.
39 if ( is_array( $core_vulnerabilities ) ) {
40 foreach ( $core_vulnerabilities as $vulnerability ) {
41
42 $what = array();
43 if ( isset( $vulnerability['impact']['cwe'] ) ) {
44 foreach ( $vulnerability['impact']['cwe'] as $vulnerability_cwe ) {
45 $what[] = '<div><b>' . wp_kses( (string) $vulnerability_cwe['name'], 'strip' ) . '</b></div><div><i>' . wp_kses_post( (string) $vulnerability_cwe['description'] ) . '</i></div>';
46 }
47 }
48
49 $sources = array();
50 if ( isset( $vulnerability['source'] ) ) {
51 foreach ( $vulnerability['source'] as $vulnerability_source ) {
52 $sources[] = '<a href="' . esc_url( (string) $vulnerability_source['link'] ) . '" target="_blank" rel="external nofollow noopener noreferrer">[+]</a>&nbsp;' . wp_kses( (string) $vulnerability_source['name'], 'strip' );
53 }
54 }
55 $source = count( $sources ) ? '<div style="padding-bottom: 5px;">' . implode( '<br>', $sources ) . '</div>' : '';
56
57 $score = isset( $vulnerability['impact']['cvss']['score'] ) ? number_format( (float) $vulnerability['impact']['cvss']['score'], 1, '.', '' ) : null;
58 $severity = isset( $vulnerability['impact']['cvss']['severity'] ) ? wpvulnerability_severity( $vulnerability['impact']['cvss']['severity'] ) : null;
59
60 $information .= '<tr>';
61 $information .= '<td style="max-width: 256px; min-width: 96px;">WordPress <b>' . wp_kses( (string) $vulnerability['name'], 'strip' ) . '</b></td>';
62 $information .= '<td>';
63 if ( count( $what ) ) {
64 $information .= '<div style="padding-bottom: 5px;">' . implode( '', $what ) . '</div>';
65 }
66 if ( ! is_null( $score ) || ! is_null( $severity ) ) {
67 $information .= '<div style="padding-bottom: 5px;">';
68 if ( ! is_null( $score ) ) {
69 $information .= '<div>' . __( 'Global score: ', 'wpvulnerability' ) . $score . ' / 10</div>';
70 }
71 if ( ! is_null( $severity ) ) {
72 $information .= '<div>' . __( 'Severity: ', 'wpvulnerability' ) . $severity . '</div>';
73 }
74 $information .= '</div>';
75 }
76 $information .= wp_kses( (string) $source, 'post' );
77 $information .= '</td>';
78 $information .= '</tr>';
79 }
80 }
81
82 $information .= '</table>';
83
84 echo $information; // phpcs:ignore
85 }
86
87 /**
88 * Retrieves vulnerabilities for a given WordPress core version and updates its data.
89 *
90 * @since 2.0.0
91 *
92 * @return array|false The updated core data array or false if no vulnerabilities are found.
93 */
94 function wpvulnerability_get_fresh_core_vulnerabilities() {
95
96 // Get the core version and sanitize it.
97 $version = wpvulnerability_sanitize_version( get_bloginfo( 'version' ) );
98
99 // Retrieve vulnerabilities for the core version.
100 $response = wpvulnerability_get_core( $version, 0 );
101
102 $core_data = array();
103
104 // If no vulnerabilities are found, return false.
105 if ( empty( $response ) ) {
106 return false;
107 }
108
109 // If vulnerabilities are found, update the core data.
110 foreach ( $response as $v ) {
111 if ( isset( $v['name'], $v['source'], $v['impact'] ) ) { // Ensure expected keys exist.
112 $core_data[] = array(
113 'name' => wp_kses( (string) $v['name'], 'strip' ),
114 'source' => $v['source'],
115 'impact' => $v['impact'],
116 );
117 }
118 }
119
120 return ! empty( $core_data ) ? $core_data : false; // Return false if core_data is empty.
121 }
122
123 /**
124 * Get Vulnerabilities
125 *
126 * Retrieves and caches the vulnerabilities for the installed WordPress core version.
127 *
128 * @since 2.0.0
129 *
130 * @return string JSON-encoded array of core data with vulnerabilities and vulnerable status.
131 */
132 function wpvulnerability_core_get_installed() {
133
134 $wpvulnerability_core_vulnerable = 0;
135 $current_version = wpvulnerability_sanitize_version( get_bloginfo( 'version' ) );
136
137 // Get fresh core vulnerabilities.
138 $core = wpvulnerability_get_fresh_core_vulnerabilities();
139
140 // Check if vulnerabilities were found and count them.
141 if ( is_array( $core ) && count( $core ) > 0 ) {
142 $wpvulnerability_core_vulnerable = count( $core );
143 }
144
145 // Cache the vulnerability data and the timestamp for cache expiration.
146 if ( is_multisite() ) {
147 update_site_option( 'wpvulnerability-core', wp_json_encode( $core ) );
148 update_site_option( 'wpvulnerability-core-vulnerable', wp_json_encode( number_format( $wpvulnerability_core_vulnerable, 0, '.', '' ) ) );
149 update_site_option( 'wpvulnerability-core-cache', wp_json_encode( number_format( time() + ( 3600 * wpvulnerability_cache_hours() ), 0, '.', '' ) ) );
150 update_site_option( 'wpvulnerability-core-version', wp_json_encode( $current_version ) );
151 } else {
152 update_option( 'wpvulnerability-core', wp_json_encode( $core ) );
153 update_option( 'wpvulnerability-core-vulnerable', wp_json_encode( number_format( $wpvulnerability_core_vulnerable, 0, '.', '' ) ) );
154 update_option( 'wpvulnerability-core-cache', wp_json_encode( number_format( time() + ( 3600 * wpvulnerability_cache_hours() ), 0, '.', '' ) ) );
155 update_option( 'wpvulnerability-core-version', wp_json_encode( $current_version ) );
156 }
157
158 // Return the JSON-encoded array of core vulnerabilities.
159 return wp_json_encode( $core );
160 }
161
162 /**
163 * Get cached core vulnerabilities without refreshing external data.
164 *
165 * @since 2.0.0
166 * @since 4.1.2 Refreshes when the stored WordPress core version differs from the running version.
167 *
168 * @return array Array of core with their vulnerabilities.
169 */
170 function wpvulnerability_core_get_vulnerabilities() {
171
172 if ( is_multisite() ) {
173 $core_data = json_decode( get_site_option( 'wpvulnerability-core' ), true );
174 } else {
175 $core_data = json_decode( get_option( 'wpvulnerability-core' ), true );
176 }
177
178 return is_array( $core_data ) ? $core_data : array();
179 }
180
181 /**
182 * Update the core cache and remove any old cache data.
183 *
184 * @since 2.0.0
185 *
186 * @return void
187 */
188 function wpvulnerability_core_get_vulnerabilities_clean() {
189 wpvulnerability_clear_cache( 'core' );
190 wpvulnerability_core_get_installed();
191 }
192
193 /**
194 * Adds vulnerability information after the core version and notices on the update-core.php page.
195 *
196 * @since 2.0.0
197 *
198 * @return void
199 */
200 function wpvulnerability_core_page() {
201
202 // Check if the current page is the update-core.php page.
203 global $pagenow;
204 if ( wpvulnerability_analyze_filter( 'core' ) && 'update-core.php' === $pagenow && wpvulnerability_capabilities() ) {
205
206 // Get the vulnerabilities for the core.
207 $core = wpvulnerability_core_get_vulnerabilities();
208
209 // If there are vulnerabilities, add an action to display them after the core auto updates settings.
210 if ( is_array( $core ) && ! empty( $core ) ) {
211 add_action( 'after_core_auto_updates_settings', 'wpvulnerability_core_info_after' );
212 }
213 }
214 }
215 // Add notices for vulnerable core on the core page.
216 add_action( 'admin_head', 'wpvulnerability_core_page' );
217