PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 6.3.0
Defender Security – Malware Scanner, Login Security & Firewall v6.3.0
6.3.0 6.2.3 6.2.4 6.2.0 6.2.1 6.2.2 6.1.0 5.3.1 5.4.0 5.4.1 5.5.0 5.5.1 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.7.2 5.8.0 5.8.1 5.9.0 6.0.0 6.0.1 3.0.1 3.1.0 All 141 releases
← All changes | src/behavior/scan-item/class-core-integrity.php +82 -9 5.6.2 → 6.3.0 View file →
@@ -15,8 +15,9 @@
15 15 use WP_Defender\Traits\Formats;
16 16 use WP_Defender\Model\Scan_Item;
17 17 use WP_Defender\Traits\File_Operations;
18 18 use WP_Defender\Controller\Scan as Scan_Controller;
19 +use WP_Defender\Behavior\Scan\Core_Integrity as Core_Integrity_Scan;
19 20 use WP_Filesystem_Base;
20 21
21 22 /**
22 23 * This class represents a behavior related to core integrity in the WP_Defender plugin.
@@ -66,9 +67,9 @@
66 67 global $wp_version;
67 68 $data = $this->owner->raw_data;
68 69 $file = wp_normalize_path( $data['file'] );
69 70 $relative_path = str_replace( wp_normalize_path( ABSPATH ), '', $file );
70 - $source_file_url = "http://core.svn.wordpress.org/tags/$wp_version/" . $relative_path;
71 + $source_file_url = "https://core.svn.wordpress.org/tags/$wp_version/" . $relative_path;
71 72 $ds = DIRECTORY_SEPARATOR;
72 73 if ( ! function_exists( 'download_url' ) ) {
73 74 require_once ABSPATH . 'wp-admin' . $ds . 'includes' . $ds . 'file.php';
74 75 }
@@ -77,13 +78,65 @@
77 78 return $tmp;
78 79 }
79 80 $content = $wp_filesystem->get_contents( $tmp );
80 81 wp_delete_file( $tmp );
82 + $trusted_checksum = $this->get_trusted_checksum( $relative_path );
81 83
84 + if ( ! is_string( $content ) || ! is_string( $trusted_checksum ) ) {
85 + return new WP_Error(
86 + 'defender_core_checksum_unavailable',
87 + esc_html__( 'The trusted WordPress core checksum is unavailable.', 'defender-security' )
88 + );
89 + }
90 +
91 + if ( ! hash_equals( strtolower( $trusted_checksum ), md5( $content ) ) ) {
92 + return new WP_Error(
93 + 'defender_core_checksum_mismatch',
94 + esc_html__( 'The downloaded WordPress core file failed checksum verification.', 'defender-security' )
95 + );
96 + }
97 +
82 98 return $content;
83 99 }
84 100
85 101 /**
102 + * Get the trusted WordPress checksum for a core file.
103 + *
104 + * New scan items persist the checksum used to identify the modification.
105 + * The temporary scan cache and the WordPress checksum API are fallbacks for
106 + * scan items created before that checksum was stored with the issue.
107 + *
108 + * @param string $relative_path Core file path relative to ABSPATH.
109 + * @return string|null
110 + */
111 + private function get_trusted_checksum( $relative_path ) {
112 + $data = $this->owner->raw_data;
113 + if ( isset( $data['checksum'] ) && is_string( $data['checksum'] ) ) {
114 + return $data['checksum'];
115 + }
116 +
117 + $checksums = get_site_option( Core_Integrity_Scan::CACHE_CHECKSUMS, array() );
118 + if ( is_array( $checksums ) && isset( $checksums[ $relative_path ] ) && is_string( $checksums[ $relative_path ] ) ) {
119 + return $checksums[ $relative_path ];
120 + }
121 +
122 + if ( ! function_exists( 'get_core_checksums' ) ) {
123 + require_once ABSPATH . 'wp-admin/includes/update.php';
124 + }
125 +
126 + global $wp_version, $wp_local_package;
127 + $locale = isset( $wp_local_package ) && '' !== $wp_local_package ? $wp_local_package : 'en_US';
128 + $checksums = get_core_checksums( $wp_version, $locale );
129 + if ( isset( $checksums[ $wp_version ] ) && is_array( $checksums[ $wp_version ] ) ) {
130 + $checksums = $checksums[ $wp_version ];
131 + }
132 +
133 + return is_array( $checksums ) && isset( $checksums[ $relative_path ] ) && is_string( $checksums[ $relative_path ] )
134 + ? $checksums[ $relative_path ]
135 + : null;
136 + }
137 +
138 + /**
86 139 * Restore the file with its origin content.
87 140 *
88 141 * @return void|array|WP_Error
89 142 */
@@ -89,12 +142,13 @@
89 142 */
90 143 public function resolve() {
91 144 global $wp_filesystem;
92 145 // Initialize the WP filesystem, no more using 'file-put-contents' function.
93 - if ( empty( $wp_filesystem ) ) {
94 - include_once ABSPATH . '/wp-admin/includes/file.php';
146 + if ( ! $wp_filesystem instanceof WP_Filesystem_Base ) {
147 + require_once ABSPATH . '/wp-admin/includes/file.php';
95 148 WP_Filesystem();
96 149 }
150 +
97 151 $data = $this->owner->raw_data;
98 152 if ( 'modified' !== $data['type'] ) {
99 153 // Should not be here unless case changed.
100 154 return;
@@ -131,12 +185,26 @@
131 185 *
132 186 * @return array
133 187 */
134 188 public function ignore(): array {
135 - $scan = Scan::get_last();
136 - $scan->ignore_issue( $this->owner->id );
189 + $scan = Scan::get_last();
190 + $data = $this->owner->raw_data;
191 + $issue_name = '<b>' . pathinfo( $data['file'], PATHINFO_BASENAME ) . '</b>';
192 + $res = $scan->ignore_issue( $this->owner->id );
193 + if ( ! $res ) {
194 + return array(
195 + 'type_notice' => 'error',
196 + 'message' => $this->get_failed_ignore_result( $issue_name ),
197 + );
198 + }
137 199
138 - return array( 'message' => esc_html__( 'The suspicious file has been successfully ignored.', 'defender-security' ) );
200 + return array(
201 + 'message' => sprintf(
202 + /* translators: %s: Scan issue name. */
203 + esc_html__( 'You’ve successfully ignored the security issue related to %s.', 'defender-security' ),
204 + $issue_name
205 + ),
206 + );
139 207 }
140 208
141 209 /**
142 210 * Restore the ignored suspicious file.
@@ -188,12 +256,13 @@
188 256 */
189 257 public function pull_src(): array {
190 258 global $wp_filesystem;
191 259 // Initialize the WP filesystem, no more using 'file-put-contents' function.
192 - if ( empty( $wp_filesystem ) ) {
193 - include_once ABSPATH . '/wp-admin/includes/file.php';
260 + if ( ! $wp_filesystem instanceof WP_Filesystem_Base ) {
261 + require_once ABSPATH . '/wp-admin/includes/file.php';
194 262 WP_Filesystem();
195 263 }
264 +
196 265 $data = $this->owner->raw_data;
197 266 if ( ! file_exists( $data['file'] ) && ! is_dir( $data['file'] ) ) {
198 267 return array(
199 268 'code' => '',
@@ -208,11 +277,13 @@
208 277
209 278 return array( 'code' => implode( PHP_EOL, $dir_tree->get_dir_tree() ) );
210 279 case 'modified':
211 280 default:
281 + $origin = $this->get_origin_code();
282 +
212 283 return array(
213 284 'code' => $wp_filesystem->get_contents( $data['file'] ),
214 - 'origin' => $this->get_origin_code(),
285 + 'origin' => is_string( $origin ) ? $origin : '',
215 286 );
216 287 }
217 288 }
218 289
@@ -229,6 +300,8 @@
229 300 return esc_html__( 'This directory does not belong to WordPress core', 'defender-security' );
230 301 } elseif ( 'modified' === $data['type'] ) {
231 302 return esc_html__( 'This WordPress core file appears modified', 'defender-security' );
232 303 }
304 +
305 + return '';
233 306 }
234 307 }