wordfence
Last commit date
css
13 years ago
images
13 years ago
js
13 years ago
lib
13 years ago
tmp
13 years ago
.htaccess
13 years ago
readme.txt
13 years ago
screenshot-1.png
14 years ago
screenshot-2.png
14 years ago
screenshot-3.png
14 years ago
screenshot-4.png
14 years ago
screenshot-5.png
14 years ago
visitor.php
13 years ago
wfscan.php
13 years ago
wordfence.php
13 years ago
wfscan.php
175 lines
| 1 | <?php |
| 2 | /* Don't remove this line. WFSOURCEVISIBLE */ |
| 3 | define('WORDFENCE_VERSIONONLY_MODE', true); //So that we can include wordfence.php and get the version constant |
| 4 | ignore_user_abort(true); |
| 5 | $wordfence_wp_version = false; |
| 6 | if ( !defined('ABSPATH') ) { |
| 7 | /** Set up WordPress environment */ |
| 8 | if($_SERVER['SCRIPT_FILENAME']){ |
| 9 | $wfBaseDir = preg_replace('/[^\/]+\/[^\/]+\/[^\/]+\/wfscan\.php$/', '', $_SERVER['SCRIPT_FILENAME']); |
| 10 | require_once($wfBaseDir . 'wp-load.php'); |
| 11 | global $wp_version; |
| 12 | global $wordfence_wp_version; |
| 13 | require($wfBaseDir . 'wp-includes/version.php'); |
| 14 | $wordfence_wp_version = $wp_version; |
| 15 | } else { |
| 16 | require_once('../../../wp-load.php'); |
| 17 | require_once('../../../wp-includes/version.php'); |
| 18 | } |
| 19 | } |
| 20 | require_once('wordfence.php'); |
| 21 | require_once('lib/wordfenceConstants.php'); |
| 22 | require_once('lib/wfScanEngine.php'); |
| 23 | |
| 24 | class wfScan { |
| 25 | public static $debugMode = false; |
| 26 | public static $errorHandlingOn = true; |
| 27 | private static $peakMemAtStart = 0; |
| 28 | public static function wfScanMain(){ |
| 29 | self::$peakMemAtStart = memory_get_peak_usage(); |
| 30 | $db = new wfDB(); |
| 31 | if($db->errorMsg){ |
| 32 | self::errorExit("Could not connect to database to start scan: " . $db->errorMsg); |
| 33 | } |
| 34 | if(! wordfence::wfSchemaExists()){ |
| 35 | self::errorExit("Looks like the Wordfence database tables have been deleted. You can fix this by de-activating and re-activating the Wordfence plugin from your Plugins menu."); |
| 36 | } |
| 37 | if(wfUtils::isAdmin() && $_GET['debugMode'] == '1'){ |
| 38 | header('Content-type: text/plain'); |
| 39 | wordfence::status(1, 'info', "Running in debug mode and writing directly to browser."); |
| 40 | if(! wp_verify_nonce($_GET['nonce'], 'wp-ajax')){ |
| 41 | echo("The security key (nonce) provided for this debug scan is invalid. Please close this window, refresh your options page and try again."); |
| 42 | exit(); |
| 43 | } |
| 44 | self::$debugMode = true; |
| 45 | wordfence::$printStatus = true; |
| 46 | } else { |
| 47 | wordfence::status(4, 'info', "Scan engine received request."); |
| 48 | wordfence::status(4, 'info', "Checking cronkey header"); |
| 49 | if(! $_SERVER['HTTP_X_WORDFENCE_CRONKEY']){ |
| 50 | self::errorExit("The Wordfence scanner did not receive the x_wordfence_cronkey secure header."); |
| 51 | } |
| 52 | wordfence::status(4, 'info', "Fetching stored cronkey for comparison."); |
| 53 | $currentCronKey = wfConfig::get('currentCronKey', false); |
| 54 | if(! $currentCronKey){ |
| 55 | self::errorExit("Wordfence could not find a saved cron key to start the scan."); |
| 56 | } |
| 57 | |
| 58 | wordfence::status(4, 'info', "Exploding stored cronkey"); |
| 59 | $savedKey = explode(',',$currentCronKey); |
| 60 | if(time() - $savedKey[0] > 60){ |
| 61 | self::errorExit("The key used to start a scan has expired."); |
| 62 | } //keys only last 60 seconds and are used within milliseconds of creation |
| 63 | wordfence::status(4, 'info', "Checking saved cronkey against cronkey header"); |
| 64 | if($savedKey[1] != $_SERVER['HTTP_X_WORDFENCE_CRONKEY']){ |
| 65 | self::errorExit("Wordfence could not start a scan because the cron key does not match the saved key."); |
| 66 | } |
| 67 | wordfence::status(4, 'info', "Deleting stored cronkey"); |
| 68 | wfConfig::set('currentCronKey', ''); |
| 69 | } |
| 70 | |
| 71 | ini_set('max_execution_time', 1800); //30 mins |
| 72 | wordfence::status(4, 'info', "Becoming admin for scan"); |
| 73 | self::becomeAdmin(); |
| 74 | |
| 75 | $isFork = ($_GET['isFork'] == '1' ? true : false); |
| 76 | |
| 77 | if(! $isFork){ |
| 78 | wordfence::status(4, 'info', "Checking if scan is already running"); |
| 79 | if(! wfUtils::getScanLock()){ |
| 80 | self::errorExit("There is already a scan running."); |
| 81 | } |
| 82 | } |
| 83 | wordfence::status(4, 'info', "Requesting max memory"); |
| 84 | wfUtils::requestMaxMemory(); |
| 85 | wordfence::status(4, 'info', "Setting up error handling environment"); |
| 86 | set_error_handler('wfScan::error_handler', E_ALL); |
| 87 | register_shutdown_function('wfScan::shutdown'); |
| 88 | if(! self::$debugMode){ |
| 89 | ob_start('wfScan::obHandler'); |
| 90 | } |
| 91 | @error_reporting(E_ALL); |
| 92 | @ini_set('display_errors','On'); |
| 93 | wordfence::status(4, 'info', "Setting up scanRunning and starting scan"); |
| 94 | $scan = false; |
| 95 | if($isFork){ |
| 96 | $scan = wfConfig::get_ser('wfsd_engine', false, true); |
| 97 | if($scan){ |
| 98 | wordfence::status(4, 'info', "Got a true deserialized value back from 'wfsd_engine' with type: " . gettype($scan)); |
| 99 | wfConfig::set('wfsd_engine', '', true); |
| 100 | } else { |
| 101 | wordfence::status(2, 'error', "Scan can't continue - stored data not found after a fork. Got type: " . gettype($scan)); |
| 102 | wfConfig::set('wfsd_engine', '', true); |
| 103 | exit(); |
| 104 | } |
| 105 | } else { |
| 106 | wordfence::statusPrep(); //Re-initializes all status counters |
| 107 | $scan = new wfScanEngine(); |
| 108 | } |
| 109 | try { |
| 110 | $scan->go(); |
| 111 | } catch (Exception $e){ |
| 112 | wfUtils::clearScanLock(); |
| 113 | wordfence::status(2, 'error', "Scan terminated with error: " . $e->getMessage()); |
| 114 | wordfence::status(10, 'info', "SUM_KILLED:Previous scan terminated with an error. See below."); |
| 115 | exit(); |
| 116 | } |
| 117 | wfUtils::clearScanLock(); |
| 118 | self::logPeakMemory(); |
| 119 | wordfence::status(2, 'info', "Wordfence used " . sprintf('%.2f', (wfConfig::get('wfPeakMemory') - self::$peakMemAtStart) / 1024 / 1024) . "MB of memory for scan. Server peak memory usage was: " . sprintf('%.2f', wfConfig::get('wfPeakMemory') / 1024 / 1024) . "MB"); |
| 120 | } |
| 121 | private static function logPeakMemory(){ |
| 122 | $oldPeak = wfConfig::get('wfPeakMemory', 0); |
| 123 | $peak = memory_get_peak_usage(); |
| 124 | if($peak > $oldPeak){ |
| 125 | wfConfig::set('wfPeakMemory', $peak); |
| 126 | } |
| 127 | } |
| 128 | public static function obHandler($buf){ |
| 129 | if(strlen($buf) > 1000){ |
| 130 | $buf = substr($buf, 0, 255); |
| 131 | } |
| 132 | if(empty($buf) === false && preg_match('/[a-zA-Z0-9]+/', $buf)){ |
| 133 | wordfence::status(1, 'error', $buf); |
| 134 | } |
| 135 | } |
| 136 | public static function error_handler($errno, $errstr, $errfile, $errline){ |
| 137 | if(self::$errorHandlingOn){ |
| 138 | if(preg_match('/wordfence\//', $errfile)){ |
| 139 | $level = 1; //It's one of our files, so level 1 |
| 140 | } else { |
| 141 | $level = 4; //It's someone elses plugin so only show if debug is enabled |
| 142 | } |
| 143 | wordfence::status($level, 'error', "$errstr ($errno) File: $errfile Line: $errline"); |
| 144 | } |
| 145 | } |
| 146 | public static function shutdown(){ |
| 147 | self::logPeakMemory(); |
| 148 | } |
| 149 | private static function errorExit($msg){ |
| 150 | echo json_encode(array('errorMsg' => $msg)); |
| 151 | exit(); |
| 152 | } |
| 153 | public static function becomeAdmin(){ |
| 154 | global $wpdb; |
| 155 | $ws = $wpdb->get_results("SELECT ID, user_login FROM $wpdb->users"); |
| 156 | $users = array(); |
| 157 | foreach($ws as $user){ |
| 158 | $userDat = get_userdata($user->ID); |
| 159 | array_push($users, array( |
| 160 | 'id' => $user->ID, |
| 161 | 'user_login' => $user->user_login, |
| 162 | 'level' => $userDat->user_level |
| 163 | )); |
| 164 | } |
| 165 | usort($users, 'wfScan::usort'); |
| 166 | wp_set_current_user($users[0]['id'], $users[0]['user_login']); |
| 167 | } |
| 168 | public static function usort($b, $a){ |
| 169 | if($a['level'] == $b['level']){ return 0; } |
| 170 | return ($a['level'] < $b['level']) ? -1 : 1; |
| 171 | } |
| 172 | } |
| 173 | wfScan::wfScanMain(); |
| 174 | ?> |
| 175 |