Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
0.00% |
0 / 91 |
|
0.00% |
0 / 7 |
CRAP | |
0.00% |
0 / 1 |
| apply_filters_ref_array | |
0.00% |
0 / 21 |
|
0.00% |
0 / 1 |
72 | |||
| VP_Site_Scanner | |
0.00% |
0 / 66 |
|
0.00% |
0 / 6 |
1560 | |
0.00% |
0 / 1 |
| __construct | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
56 | |||
| _custom_cron | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 | |||
| _scan_site | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
110 | |||
| _scan_clean_up | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
20 | |||
| _scan_batch | |
0.00% |
0 / 31 |
|
0.00% |
0 / 1 |
240 | |||
| init | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
| 1 | <?php |
| 2 | // don't call the file directly |
| 3 | defined( 'ABSPATH' ) || die( 0 ); |
| 4 | |
| 5 | require_once __DIR__ . '/vp-scanner.php'; |
| 6 | |
| 7 | if ( !function_exists( 'apply_filters_ref_array' ) ) : |
| 8 | |
| 9 | function apply_filters_ref_array($tag, $args) { |
| 10 | global $wp_filter, $merged_filters, $wp_current_filter; |
| 11 | |
| 12 | // Do 'all' actions first |
| 13 | if ( isset($wp_filter['all']) ) { |
| 14 | $all_args = func_get_args(); |
| 15 | $wp_current_filter[] = $tag; |
| 16 | _wp_call_all_hook($all_args); |
| 17 | } |
| 18 | |
| 19 | if ( !isset($wp_filter[$tag]) ) { |
| 20 | if ( isset($wp_filter['all']) ) |
| 21 | array_pop($wp_current_filter); |
| 22 | return $args[0]; |
| 23 | } |
| 24 | |
| 25 | if ( !isset($wp_filter['all']) ) |
| 26 | $wp_current_filter[] = $tag; |
| 27 | |
| 28 | // Sort |
| 29 | if ( !isset( $merged_filters[ $tag ] ) ) { |
| 30 | ksort($wp_filter[$tag]); |
| 31 | $merged_filters[ $tag ] = true; |
| 32 | } |
| 33 | |
| 34 | reset( $wp_filter[ $tag ] ); |
| 35 | |
| 36 | do { |
| 37 | foreach( (array) current($wp_filter[$tag]) as $the_ ) |
| 38 | if ( !is_null($the_['function']) ) |
| 39 | $args[0] = call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args'])); |
| 40 | |
| 41 | } while ( next($wp_filter[$tag]) !== false ); |
| 42 | |
| 43 | array_pop( $wp_current_filter ); |
| 44 | |
| 45 | return $args[0]; |
| 46 | } |
| 47 | |
| 48 | endif; |
| 49 | |
| 50 | class VP_Site_Scanner { |
| 51 | function __construct() { |
| 52 | // Only scan once in multisites. |
| 53 | if( function_exists( 'is_main_site' ) && !is_main_site() ) |
| 54 | return; |
| 55 | add_action( 'vp_scan_site' , array( $this, '_scan_site') ); |
| 56 | add_filter( 'cron_schedules' , array( $this, '_custom_cron' ) ); |
| 57 | add_action( 'vp_scan_next_batch', array( $this, '_scan_batch' ) ); |
| 58 | |
| 59 | $signatures = get_option( '_vp_signatures' ); |
| 60 | if ( $signatures && ! wp_next_scheduled( 'vp_scan_site' ) ) |
| 61 | wp_schedule_event( time(), 'daily', 'vp_scan_site' ); |
| 62 | if ( $signatures && ! wp_next_scheduled( 'vp_scan_next_batch' ) ) |
| 63 | wp_schedule_event( time(), 'five_minutes_interval', 'vp_scan_next_batch' ); |
| 64 | } |
| 65 | |
| 66 | function _custom_cron( $schedules ) { |
| 67 | $schedules['five_minutes_interval'] = array( |
| 68 | 'interval' => 300, |
| 69 | 'display' => __( 'Once every five minutes' , 'vaultpress'), |
| 70 | ); |
| 71 | return $schedules; |
| 72 | } |
| 73 | |
| 74 | function _scan_site() { |
| 75 | if ( !get_option( '_vp_current_scan' ) ) { |
| 76 | $ignore_symlinks = get_option( '_vp_ignore_symlinks', false ); |
| 77 | $paths = array( 'root' => new VP_FileScan( ABSPATH, $ignore_symlinks ) ); |
| 78 | |
| 79 | // Is WP_CONTENT_DIR inside ABSPATH? |
| 80 | if ( is_dir( WP_CONTENT_DIR ) && strpos( realpath( WP_CONTENT_DIR ), realpath( ABSPATH ) . DIRECTORY_SEPARATOR ) !== 0 ) |
| 81 | $paths['content'] = new VP_FileScan( WP_CONTENT_DIR, $ignore_symlinks ); |
| 82 | |
| 83 | // Is WP_PLUGIN_DIR inside ABSPATH or WP_CONTENT_DIR? |
| 84 | if ( is_dir( WP_PLUGIN_DIR ) && strpos( realpath( WP_PLUGIN_DIR ), realpath( WP_CONTENT_DIR ) . DIRECTORY_SEPARATOR ) !== 0 && strpos( realpath( WP_PLUGIN_DIR ), realpath( ABSPATH ) . DIRECTORY_SEPARATOR ) !== 0 ) |
| 85 | $paths['plugins'] = new VP_FileScan( WP_PLUGIN_DIR, $ignore_symlinks ); |
| 86 | |
| 87 | // Is WPMU_PLUGIN_DIR inside ABSPATH or WP_CONTENT_DIR? |
| 88 | if ( is_dir( WPMU_PLUGIN_DIR ) && strpos( realpath( WPMU_PLUGIN_DIR ), realpath( WP_CONTENT_DIR ) . DIRECTORY_SEPARATOR ) !== 0 && strpos( realpath( WPMU_PLUGIN_DIR ), realpath( ABSPATH ) . DIRECTORY_SEPARATOR ) !== 0 ) |
| 89 | $paths['mu-plugins'] = new VP_FileScan( WPMU_PLUGIN_DIR, $ignore_symlinks ); |
| 90 | |
| 91 | update_option( '_vp_current_scan', $paths ); |
| 92 | } |
| 93 | } |
| 94 | |
| 95 | function _scan_clean_up( &$paths, $type = null ) { |
| 96 | if( is_array( $paths ) ) |
| 97 | unset( $paths[$type] ); |
| 98 | if ( empty( $paths ) || !is_array( $paths ) ) { |
| 99 | delete_option( '_vp_current_scan' ); |
| 100 | return true; |
| 101 | } |
| 102 | return false; |
| 103 | } |
| 104 | |
| 105 | function _scan_batch() { |
| 106 | $paths = get_option( '_vp_current_scan' ); |
| 107 | if ( empty( $paths ) || $this->_scan_clean_up( $paths ) ) |
| 108 | return false; |
| 109 | |
| 110 | if ( ! is_array( $paths ) ) { |
| 111 | return false; |
| 112 | } |
| 113 | |
| 114 | reset( $paths ); |
| 115 | |
| 116 | $type = null; |
| 117 | $current = false; |
| 118 | foreach ( $paths as $type => $current ) { |
| 119 | break; |
| 120 | } |
| 121 | |
| 122 | if ( !is_object( $current ) || empty( $current->last_dir ) ) |
| 123 | return $this->_scan_clean_up( $paths, $type ); |
| 124 | |
| 125 | $default_batch_limit = 400; |
| 126 | if ( ! function_exists( 'set_time_limit' ) || ! @set_time_limit( 0 ) ) { |
| 127 | $default_batch_limit = 100; // avoid timeouts |
| 128 | } |
| 129 | |
| 130 | $GLOBALS['vp_signatures'] = get_option( '_vp_signatures' ); |
| 131 | if ( empty( $GLOBALS['vp_signatures'] ) ) |
| 132 | return false; |
| 133 | |
| 134 | $limit = get_option( '_vp_batch_file_size', $default_batch_limit ); |
| 135 | $files = $current->get_files( $limit ); |
| 136 | |
| 137 | // No more files to scan. |
| 138 | if ( !$current->last_dir || count( $files ) < $limit ) |
| 139 | unset( $paths[$type] ); |
| 140 | |
| 141 | update_option( '_vp_current_scan', $paths ); |
| 142 | $results = array(); |
| 143 | foreach ( $files as $file ) { |
| 144 | $verdict = vp_scan_file( $file ); |
| 145 | if ( !empty( $verdict ) ) |
| 146 | $results[$file] = array( 'hash' => @md5_file( $file ), 'verdict' => $verdict ); |
| 147 | } |
| 148 | |
| 149 | if ( !empty( $results ) ) { |
| 150 | $vaultpress = VaultPress::init(); |
| 151 | $vaultpress->add_ping( 'security', array( 'suspicious_v2' => $results ) ); |
| 152 | } |
| 153 | } |
| 154 | |
| 155 | static function &init() { |
| 156 | static $instance = false; |
| 157 | if ( !$instance ) |
| 158 | $instance = new VP_Site_Scanner(); |
| 159 | return $instance; |
| 160 | } |
| 161 | } |
| 162 | VP_Site_Scanner::init(); |