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/component/security-tweaks/servers/class-apache.php +74 -28 5.5.1 → 6.3.0 View file →
@@ -7,8 +7,9 @@
7 7
8 8 namespace WP_Defender\Component\Security_Tweaks\Servers;
9 9
10 10 use WP_Error;
11 +use WP_Filesystem_Base;
11 12
12 13 /**
13 14 * Provides methods to apply and revert security rules on servers.
14 15 */
@@ -83,9 +84,9 @@
83 84 public function get_error_by_file_path( $file_path ) {
84 85 return new WP_Error(
85 86 'defender_file_not_writable',
86 87 sprintf(
87 - /* translators: %s - file path */
88 + /* translators: %s: file path */
88 89 esc_html__( 'The file %s is not writable', 'defender-security' ),
89 90 $file_path
90 91 )
91 92 );
@@ -98,9 +99,9 @@
98 99 */
99 100 public function process() {
100 101 global $wp_filesystem;
101 102 // Initialize the WP filesystem, no more using 'file-put-contents' function.
102 - if ( empty( $wp_filesystem ) ) {
103 + if ( ! $wp_filesystem instanceof WP_Filesystem_Base ) {
103 104 require_once ABSPATH . '/wp-admin/includes/file.php';
104 105 WP_Filesystem();
105 106 }
106 107 if ( 'protect-information' === $this->type ) {
@@ -106,9 +107,9 @@
106 107 if ( 'protect-information' === $this->type ) {
107 108 $ht_access_path = ABSPATH . '.htaccess';
108 109 // Create a htaccess-file if it doesn't exist.
109 110 if ( ! is_file( $ht_access_path )
110 - && false === (bool) file_put_contents( $ht_access_path, '', LOCK_EX ) // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents
111 + && false === file_put_contents( $ht_access_path, '', LOCK_EX ) // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents
111 112 ) {
112 113 return $this->get_error_by_file_path( $ht_access_path );
113 114 }
114 115 // If the htaccess-file is existed.
@@ -179,8 +180,10 @@
179 180 update_site_option( "defender_security_tweeks_{$this->type}", $settings );
180 181
181 182 return true;
182 183 }
184 +
185 + return true;
183 186 }
184 187
185 188 /**
186 189 * Revert the rules.
@@ -189,9 +192,9 @@
189 192 */
190 193 public function revert() {
191 194 global $wp_filesystem;
192 195 // Initialize the WP filesystem, no more using 'file-put-contents' function.
193 - if ( empty( $wp_filesystem ) ) {
196 + if ( ! $wp_filesystem instanceof WP_Filesystem_Base ) {
194 197 require_once ABSPATH . '/wp-admin/includes/file.php';
195 198 WP_Filesystem();
196 199 }
197 200 if ( 'protect-information' === $this->type ) {
@@ -245,8 +248,10 @@
245 248 }
246 249
247 250 return delete_site_option( "defender_security_tweeks_{$this->type}" );
248 251 }
252 +
253 + return true;
249 254 }
250 255
251 256 /**
252 257 * Get Apache rule depending on the version.
@@ -255,9 +260,9 @@
255 260 */
256 261 public function get_rules() {
257 262 $rules = array(
258 263 PHP_EOL . '## WP Defender - Prevent information disclosure ##' . PHP_EOL,
259 - '<FilesMatch "\.(md|exe|sh|bak|inc|pot|po|mo|log|sql)$">' . PHP_EOL .
264 + '<FilesMatch "(?i)\.(md|exe|sh|bak|inc|pot|po|mo|log|sql)$">' . PHP_EOL .
260 265 'Require all denied' . PHP_EOL .
261 266 '</FilesMatch>' . PHP_EOL,
262 267 '<Files robots.txt>' . PHP_EOL .
263 268 'Require all granted' . PHP_EOL .
@@ -270,9 +275,9 @@
270 275
271 276 if ( version_compare( $this->get_version(), '2.4', '<' ) ) {
272 277 $rules = array(
273 278 PHP_EOL . '## WP Defender - Prevent information disclosure ##' . PHP_EOL,
274 - '<FilesMatch "\.(md|exe|sh|bak|inc|pot|po|mo|log|sql)$">' . PHP_EOL .
279 + '<FilesMatch "(?i)\.(md|exe|sh|bak|inc|pot|po|mo|log|sql)$">' . PHP_EOL .
275 280 'Order allow,deny' . PHP_EOL .
276 281 'Deny from all' . PHP_EOL .
277 282 '</FilesMatch>' . PHP_EOL,
278 283 '<Files robots.txt>' . PHP_EOL .
@@ -288,8 +293,27 @@
288 293 return $rules;
289 294 }
290 295
291 296 /**
297 + * Get LiteSpeed .htaccess rules for display in the browser, independent of the current server detection.
298 + *
299 + * @return string
300 + */
301 + public function get_litespeed_rules_for_instruction(): string {
302 + if ( 'prevent-php-executed' !== $this->type ) {
303 + return '';
304 + }
305 +
306 + $rules = '## WP Defender - Protect PHP Executed ##' . PHP_EOL;
307 + $rules .= '<Files *.php>' . PHP_EOL;
308 + $rules .= 'Require all denied' . PHP_EOL;
309 + $rules .= '</Files>' . PHP_EOL;
310 + $rules .= '## WP Defender - End ##' . PHP_EOL;
311 +
312 + return $rules;
313 + }
314 +
315 + /**
292 316 * Get Apache rule depending on the version for instruction on browser.
293 317 *
294 318 * @return string
295 319 */
@@ -304,9 +328,9 @@
304 328 $rules .= '</Files>' . PHP_EOL;
305 329 $rules .= PHP_EOL;
306 330 $rules .= '## WP Defender - End ##' . PHP_EOL;
307 331
308 - if ( version_compare( $this->get_version(), '2.4', '<' ) ) {
332 + if ( 'apache' === Server::get_current_server() && version_compare( $this->get_version(), '2.4', '<' ) ) {
309 333 $rules = '## WP Defender - Protect PHP Executed ##' . PHP_EOL;
310 334 $rules .= PHP_EOL;
311 335 $rules .= '<Files *.php>' . PHP_EOL;
312 336 $rules .= 'Order allow,deny' . PHP_EOL;
@@ -313,8 +337,13 @@
313 337 $rules .= 'Deny from all' . PHP_EOL;
314 338 $rules .= '</Files>' . PHP_EOL;
315 339 $rules .= PHP_EOL;
316 340 $rules .= '## WP Defender - End ##' . PHP_EOL;
341 + } elseif ( 'litespeed' === Server::get_current_server() ) {
342 + $rules = '## WP Defender - Protect PHP Executed ##' . PHP_EOL;
343 + $rules .= 'RewriteEngine On' . PHP_EOL;
344 + $rules .= 'RewriteRule ^.*\.php$ - [F,L,NC]' . PHP_EOL;
345 + $rules .= '## WP Defender - End ##' . PHP_EOL;
317 346 }
318 347 }
319 348
320 349 if ( 'protect-information' === $this->type ) {
@@ -319,9 +348,9 @@
319 348
320 349 if ( 'protect-information' === $this->type ) {
321 350 $rules = '## WP Defender - Prevent information disclosure ##' . PHP_EOL;
322 351 $rules .= PHP_EOL;
323 - $rules .= '<FilesMatch "\.(md|exe|sh|bak|inc|pot|po|mo|log|sql)$">' . PHP_EOL;
352 + $rules .= '<FilesMatch "(?i)\.(md|exe|sh|bak|inc|pot|po|mo|log|sql)$">' . PHP_EOL;
324 353 $rules .= 'Require all denied' . PHP_EOL;
325 354 $rules .= '</FilesMatch>' . PHP_EOL;
326 355 $rules .= PHP_EOL;
327 356 $rules .= '<Files robots.txt>' . PHP_EOL;
@@ -336,9 +365,9 @@
336 365
337 366 if ( version_compare( $this->get_version(), '2.4', '<' ) ) {
338 367 $rules = '## WP Defender - Prevent information disclosure ##' . PHP_EOL;
339 368 $rules .= PHP_EOL;
340 - $rules .= '<FilesMatch "\.(md|exe|sh|bak|inc|pot|po|mo|log|sql)$">' . PHP_EOL;
369 + $rules .= '<FilesMatch "(?i)\.(md|exe|sh|bak|inc|pot|po|mo|log|sql)$">' . PHP_EOL;
341 370 $rules .= 'Order allow,deny' . PHP_EOL;
342 371 $rules .= 'Deny from all' . PHP_EOL;
343 372 $rules .= '</FilesMatch>' . PHP_EOL;
344 373 $rules .= PHP_EOL;
@@ -373,9 +402,9 @@
373 402 if ( ! is_array( $apache_version ) ) {
374 403 $apache_version = array();
375 404 }
376 405
377 - if ( isset( $apache_version[ $url ] ) && ! empty( $apache_version[ $url ] ) ) {
406 + if ( isset( $apache_version[ $url ] ) && is_string( $apache_version[ $url ] ) && '' !== $apache_version[ $url ] ) {
378 407 return strtolower( $apache_version[ $url ] );
379 408 }
380 409 // The default support is 2.2.
381 410 $apache_version[ $url ] = $version;
@@ -396,9 +425,9 @@
396 425 set_site_transient( self::CACHE_APACHE_VERSION, $apache_version, 3600 );
397 426 } else {
398 427 $version = apache_get_version();
399 428 $version = explode( '/', $version );
400 - $version = ! empty( $version[1] ) ? $version[1] : $version[0];
429 + $version = isset( $version[1] ) && is_string( $version[1] ) && '' !== $version[1] ? $version[1] : $version[0];
401 430 }
402 431
403 432 return $version;
404 433 }
@@ -410,20 +439,20 @@
410 439 */
411 440 public function protect_content_directory() {
412 441 global $wp_filesystem;
413 442 // Initialize the WP filesystem, no more using 'file-put-contents' function.
414 - if ( empty( $wp_filesystem ) ) {
443 + if ( ! $wp_filesystem instanceof WP_Filesystem_Base ) {
415 444 require_once ABSPATH . '/wp-admin/includes/file.php';
416 445 WP_Filesystem();
417 446 }
418 447 $ht_access_path = $this->contentdir_path;
419 448
420 - if ( empty( $ht_access_path ) ) {
449 + if ( ! is_string( $ht_access_path ) || '' === $ht_access_path ) {
421 450 $ht_access_path = WP_CONTENT_DIR . '/.htaccess';
422 451 }
423 452 // Create a htaccess-file if it doesn't exist.
424 453 if ( ! is_file( $ht_access_path )
425 - && false === (bool) file_put_contents( $ht_access_path, '', LOCK_EX ) // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents
454 + && false === file_put_contents( $ht_access_path, '', LOCK_EX ) // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents
426 455 ) {
427 456 return $this->get_error_by_file_path( $ht_access_path );
428 457 }
429 458 // If the htaccess-file is existed.
@@ -450,20 +479,20 @@
450 479 */
451 480 public function protect_includes_directory() {
452 481 global $wp_filesystem;
453 482 // Initialize the WP filesystem, no more using 'file-put-contents' function.
454 - if ( empty( $wp_filesystem ) ) {
483 + if ( ! $wp_filesystem instanceof WP_Filesystem_Base ) {
455 484 require_once ABSPATH . '/wp-admin/includes/file.php';
456 485 WP_Filesystem();
457 486 }
458 487 $ht_access_path = $this->includedir_path;
459 488
460 - if ( empty( $ht_access_path ) ) {
489 + if ( ! is_string( $ht_access_path ) || '' === $ht_access_path ) {
461 490 $ht_access_path = ABSPATH . WPINC . '/.htaccess';
462 491 }
463 492 // Create a htaccess-file if it doesn't exist.
464 493 if ( ! is_file( $ht_access_path )
465 - && false === (bool) file_put_contents( $ht_access_path, '', LOCK_EX ) // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents
494 + && false === file_put_contents( $ht_access_path, '', LOCK_EX ) // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents
466 495 ) {
467 496 return $this->get_error_by_file_path( $ht_access_path );
468 497 }
469 498 // If the htaccess-file is existed.
@@ -518,10 +547,11 @@
518 547 *
519 548 * @return void|WP_Error
520 549 */
521 550 public function protect_uploads_directory() {
522 - if ( defined( 'UPLOADS' ) ) {
523 - $this->contentdir_path = ABSPATH . UPLOADS . '/.htaccess';
551 + $path = $this->get_custom_upload_dir();
552 + if ( '' !== $path ) {
553 + $this->contentdir_path = $path;
524 554
525 555 return $this->protect_content_directory();
526 556 }
527 557 }
@@ -533,15 +563,15 @@
533 563 */
534 564 public function unprotect_content_directory() {
535 565 global $wp_filesystem;
536 566 // Initialize the WP filesystem, no more using 'file-put-contents' function.
537 - if ( empty( $wp_filesystem ) ) {
567 + if ( ! $wp_filesystem instanceof WP_Filesystem_Base ) {
538 568 require_once ABSPATH . '/wp-admin/includes/file.php';
539 569 WP_Filesystem();
540 570 }
541 571 $ht_access_path = $this->contentdir_path;
542 572
543 - if ( empty( $ht_access_path ) ) {
573 + if ( ! is_string( $ht_access_path ) || '' === $ht_access_path ) {
544 574 $ht_access_path = WP_CONTENT_DIR . '/.htaccess';
545 575 }
546 576 // Quick exit if the file does not exist.
547 577 if ( ! is_file( $ht_access_path ) ) {
@@ -566,15 +596,15 @@
566 596 */
567 597 public function unprotect_includes_directory() {
568 598 global $wp_filesystem;
569 599 // Initialize the WP filesystem, no more using 'file-put-contents' function.
570 - if ( empty( $wp_filesystem ) ) {
600 + if ( ! $wp_filesystem instanceof WP_Filesystem_Base ) {
571 601 require_once ABSPATH . '/wp-admin/includes/file.php';
572 602 WP_Filesystem();
573 603 }
574 604 $ht_access_path = $this->includedir_path;
575 605
576 - if ( empty( $ht_access_path ) ) {
606 + if ( ! is_string( $ht_access_path ) || '' === $ht_access_path ) {
577 607 $ht_access_path = ABSPATH . WPINC . '/.htaccess';
578 608 }
579 609 // Quick exit if the file does not exist.
580 610 if ( ! is_file( $ht_access_path ) ) {
@@ -591,14 +621,16 @@
591 621
592 622 /**
593 623 * Unprotect upload directory.
594 624 *
595 - * @return void
625 + * @return void|WP_Error
596 626 */
597 627 public function unprotect_upload_directory() {
598 - if ( defined( 'UPLOADS' ) ) {
599 - $this->contentdir_path = ABSPATH . UPLOADS . '/.htaccess';
600 - $this->unprotect_content_directory();
628 + $path = $this->get_custom_upload_dir();
629 + if ( '' !== $path ) {
630 + $this->contentdir_path = $path;
631 +
632 + return $this->unprotect_content_directory();
601 633 }
602 634 }
603 635
604 636 /**
@@ -606,9 +638,9 @@
606 638 *
607 639 * @param array $config to set.
608 640 */
609 641 public function set_new_htaccess_config( $config = array() ) {
610 - if ( ! empty( $config ) ) {
642 + if ( is_array( $config ) && array() !== $config ) {
611 643 $this->new_htaccess_config = $config;
612 644 }
613 645 }
614 646
@@ -641,6 +673,20 @@
641 673 $exists_rules .= PHP_EOL;
642 674 }
643 675
644 676 return $exists_rules;
677 + }
678 +
679 + /**
680 + * Get custom upload dir path.
681 + *
682 + * @return string
683 + */
684 + private function get_custom_upload_dir(): string {
685 + if ( defined( 'UPLOADS' ) ) {
686 + $upload_dir = wp_upload_dir( null, false );
687 + return $upload_dir['basedir'] . '/.htaccess';
688 + }
689 +
690 + return '';
645 691 }
646 692 }