public static function runInstall()
 {
     if (self::$runInstallCalled) {
         return;
     }
     self::$runInstallCalled = true;
     if (function_exists('ignore_user_abort')) {
         ignore_user_abort(true);
     }
     $previous_version = get_option('wordfence_version', '0.0.0');
     update_option('wordfence_version', WORDFENCE_VERSION);
     //In case we have a fatal error we don't want to keep running install.
     //EVERYTHING HERE MUST BE IDEMPOTENT
     //Remove old legacy cron job if exists
     wp_clear_scheduled_hook('wordfence_scheduled_scan');
     $schema = new wfSchema();
     $schema->createAll();
     //if not exists
     wfConfig::setDefaults();
     //If not set
     $restOfSite = wfConfig::get('cbl_restOfSiteBlocked', 'notset');
     if ($restOfSite == 'notset') {
         wfConfig::set('cbl_restOfSiteBlocked', '1');
     }
     //Install new schedule. If schedule config is blank it will install the default 'auto' schedule.
     wordfence::scheduleScans();
     if (wfConfig::get('autoUpdate') == '1') {
         wfConfig::enableAutoUpdate();
         //Sets up the cron
     }
     if (!wfConfig::get('apiKey')) {
         $api = new wfAPI('', wfUtils::getWPVersion());
         try {
             $keyData = $api->call('get_anon_api_key');
             if ($keyData['ok'] && $keyData['apiKey']) {
                 wfConfig::set('apiKey', $keyData['apiKey']);
             } else {
                 throw new Exception("Could not understand the response we received from the Wordfence servers when applying for a free API key.");
             }
         } catch (Exception $e) {
             error_log("Could not fetch free API key from Wordfence: " . $e->getMessage());
             return;
         }
     }
     wp_clear_scheduled_hook('wordfence_daily_cron');
     wp_clear_scheduled_hook('wordfence_hourly_cron');
     if (is_main_site()) {
         wp_schedule_event(time(), 'daily', 'wordfence_daily_cron');
         //'daily'
         wp_schedule_event(time(), 'hourly', 'wordfence_hourly_cron');
     }
     $db = new wfDB();
     if ($db->columnExists('wfHits', 'HTTPHeaders')) {
         //Upgrade from 3.0.4
         global $wpdb;
         $prefix = $wpdb->base_prefix;
         $count = $db->querySingle("select count(*) as cnt from {$prefix}" . "wfHits");
         if ($count > 20000) {
             $db->queryWrite("delete from {$prefix}" . "wfHits order by id asc limit " . ($count - 20000));
         }
         $db->dropColumn('wfHits', 'HTTPHeaders');
     }
     //Upgrading from 1.5.6 or earlier needs:
     $db->createKeyIfNotExists('wfStatus', 'level', 'k2');
     if (wfConfig::get('isPaid') == 'free') {
         wfConfig::set('isPaid', '');
     }
     //End upgrade from 1.5.6
     /** @var wpdb $wpdb */
     global $wpdb;
     $prefix = $wpdb->base_prefix;
     $db->queryWriteIgnoreError("alter table {$prefix}" . "wfConfig modify column val longblob");
     $db->queryWriteIgnoreError("alter table {$prefix}" . "wfBlocks add column permanent tinyint UNSIGNED default 0");
     $db->queryWriteIgnoreError("alter table {$prefix}" . "wfStatus modify column msg varchar(1000) NOT NULL");
     //3.1.2 to 3.1.4
     $db->queryWriteIgnoreError("alter table {$prefix}" . "wfBlocks modify column blockedTime bigint signed NOT NULL");
     //3.2.1 to 3.2.2
     $db->queryWriteIgnoreError("alter table {$prefix}" . "wfLockedOut modify column blockedTime bigint signed NOT NULL");
     $db->queryWriteIgnoreError("drop table if exists {$prefix}" . "wfFileQueue");
     $db->queryWriteIgnoreError("drop table if exists {$prefix}" . "wfFileChanges");
     $result = $wpdb->get_row("SHOW FIELDS FROM {$prefix}wfStatus where field = 'id'");
     if (!$result || strtolower($result->Key) != 'pri') {
         //Adding primary key to this table because some backup apps use primary key during backup.
         $db->queryWriteIgnoreError("alter table {$prefix}wfStatus add id bigint UNSIGNED NOT NULL auto_increment PRIMARY KEY");
     }
     $optScanEnabled = $db->querySingle("select val from {$prefix}" . "wfConfig where name='scansEnabled_options'");
     if ($optScanEnabled != '0' && $optScanEnabled != '1') {
         $db->queryWrite("update {$prefix}" . "wfConfig set val='1' where name='scansEnabled_options'");
     }
     $optScanEnabled = $db->querySingle("select val from {$prefix}" . "wfConfig where name='scansEnabled_heartbleed'");
     if ($optScanEnabled != '0' && $optScanEnabled != '1') {
         //Enable heartbleed if no value is set.
         wfConfig::set('scansEnabled_heartbleed', 1);
     }
     if (wfConfig::get('cacheType') == 'php' || wfConfig::get('cacheType') == 'falcon') {
         wfCache::removeCacheDirectoryHtaccess();
     }
     // IPv6 schema changes for 6.0.1
     $tables_with_ips = array('wfCrawlers', 'wfBadLeechers', 'wfBlockedIPLog', 'wfBlocks', 'wfHits', 'wfLeechers', 'wfLockedOut', 'wfLocs', 'wfLogins', 'wfReverseCache', 'wfScanners', 'wfThrottleLog', 'wfVulnScanners');
     foreach ($tables_with_ips as $ip_table) {
         $result = $wpdb->get_row("SHOW FIELDS FROM {$prefix}{$ip_table} where field = 'IP'");
         if (!$result || strtolower($result->Type) == 'binary(16)') {
             continue;
         }
         $db->queryWriteIgnoreError("ALTER TABLE {$prefix}{$ip_table} MODIFY IP BINARY(16)");
         // Just to be sure we don't corrupt the data if the alter fails.
         $result = $wpdb->get_row("SHOW FIELDS FROM {$prefix}{$ip_table} where field = 'IP'");
         if (!$result || strtolower($result->Type) != 'binary(16)') {
             continue;
         }
         $db->queryWriteIgnoreError("UPDATE {$prefix}{$ip_table} SET IP = CONCAT(LPAD(CHAR(0xff, 0xff), 12, CHAR(0)), LPAD(\n\tCHAR(\n\t\tCAST(IP as UNSIGNED) >> 24 & 0xFF,\n\t\tCAST(IP as UNSIGNED) >> 16 & 0xFF,\n\t\tCAST(IP as UNSIGNED) >> 8 & 0xFF,\n\t\tCAST(IP as UNSIGNED) & 0xFF\n\t),\n\t4,\n\tCHAR(0)\n))");
     }
     // Fix the data in the country column.
     // TODO: add version check so this doesn't run on every update.
     $ip_results = $wpdb->get_results("SELECT * FROM `{$prefix}wfBlockedIPLog` GROUP BY IP");
     if ($ip_results) {
         foreach ($ip_results as $ip_row) {
             $wpdb->query($wpdb->prepare("UPDATE `{$prefix}wfBlockedIPLog` SET countryCode = %s WHERE IP = %s", wfUtils::IP2Country(wfUtils::inet_ntop($ip_row->IP)), $ip_row->IP));
         }
     }
     //Must be the final line
 }
Beispiel #2
0
    public static function runInstall()
    {
        if (self::$runInstallCalled) {
            return;
        }
        self::$runInstallCalled = true;
        if (function_exists('ignore_user_abort')) {
            ignore_user_abort(true);
        }
        $previous_version = get_option('wordfence_version', '0.0.0');
        update_option('wordfence_version', WORDFENCE_VERSION);
        //In case we have a fatal error we don't want to keep running install.
        //EVERYTHING HERE MUST BE IDEMPOTENT
        //Remove old legacy cron job if exists
        wp_clear_scheduled_hook('wordfence_scheduled_scan');
        $schema = new wfSchema();
        $schema->createAll();
        //if not exists
        wfConfig::setDefaults();
        //If not set
        $restOfSite = wfConfig::get('cbl_restOfSiteBlocked', 'notset');
        if ($restOfSite == 'notset') {
            wfConfig::set('cbl_restOfSiteBlocked', '1');
        }
        //Install new schedule. If schedule config is blank it will install the default 'auto' schedule.
        wordfence::scheduleScans();
        if (wfConfig::get('autoUpdate') == '1') {
            wfConfig::enableAutoUpdate();
            //Sets up the cron
        }
        if (!wfConfig::get('apiKey')) {
            $api = new wfAPI('', wfUtils::getWPVersion());
            try {
                $keyData = $api->call('get_anon_api_key');
                if ($keyData['ok'] && $keyData['apiKey']) {
                    wfConfig::set('apiKey', $keyData['apiKey']);
                } else {
                    throw new Exception("Could not understand the response we received from the Wordfence servers when applying for a free API key.");
                }
            } catch (Exception $e) {
                error_log("Could not fetch free API key from Wordfence: " . $e->getMessage());
                return;
            }
        }
        wp_clear_scheduled_hook('wordfence_daily_cron');
        wp_clear_scheduled_hook('wordfence_hourly_cron');
        if (is_main_site()) {
            wp_schedule_event(time(), 'daily', 'wordfence_daily_cron');
            //'daily'
            wp_schedule_event(time(), 'hourly', 'wordfence_hourly_cron');
        }
        $db = new wfDB();
        if ($db->columnExists('wfHits', 'HTTPHeaders')) {
            //Upgrade from 3.0.4
            global $wpdb;
            $prefix = $wpdb->base_prefix;
            $count = $db->querySingle("select count(*) as cnt from {$prefix}" . "wfHits");
            if ($count > 20000) {
                $db->queryWrite("delete from {$prefix}" . "wfHits order by id asc limit " . ($count - 20000));
            }
            $db->dropColumn('wfHits', 'HTTPHeaders');
        }
        //Upgrading from 1.5.6 or earlier needs:
        $db->createKeyIfNotExists('wfStatus', 'level', 'k2');
        if (wfConfig::get('isPaid') == 'free') {
            wfConfig::set('isPaid', '');
        }
        //End upgrade from 1.5.6
        /** @var wpdb $wpdb */
        global $wpdb;
        $prefix = $wpdb->base_prefix;
        $db->queryWriteIgnoreError("alter table {$prefix}" . "wfConfig modify column val longblob");
        $db->queryWriteIgnoreError("alter table {$prefix}" . "wfBlocks add column permanent tinyint UNSIGNED default 0");
        $db->queryWriteIgnoreError("alter table {$prefix}" . "wfStatus modify column msg varchar(1000) NOT NULL");
        //3.1.2 to 3.1.4
        $db->queryWriteIgnoreError("alter table {$prefix}" . "wfBlocks modify column blockedTime bigint signed NOT NULL");
        //3.2.1 to 3.2.2
        $db->queryWriteIgnoreError("alter table {$prefix}" . "wfLockedOut modify column blockedTime bigint signed NOT NULL");
        $db->queryWriteIgnoreError("drop table if exists {$prefix}" . "wfFileQueue");
        $db->queryWriteIgnoreError("drop table if exists {$prefix}" . "wfFileChanges");
        $result = $wpdb->get_row("SHOW FIELDS FROM {$prefix}wfStatus where field = 'id'");
        if (!$result || strtolower($result->Key) != 'pri') {
            //Adding primary key to this table because some backup apps use primary key during backup.
            $db->queryWriteIgnoreError("alter table {$prefix}wfStatus add id bigint UNSIGNED NOT NULL auto_increment PRIMARY KEY");
        }
        $optScanEnabled = $db->querySingle("select val from {$prefix}" . "wfConfig where name='scansEnabled_options'");
        if ($optScanEnabled != '0' && $optScanEnabled != '1') {
            $db->queryWrite("update {$prefix}" . "wfConfig set val='1' where name='scansEnabled_options'");
        }
        $optScanEnabled = $db->querySingle("select val from {$prefix}" . "wfConfig where name='scansEnabled_heartbleed'");
        if ($optScanEnabled != '0' && $optScanEnabled != '1') {
            //Enable heartbleed if no value is set.
            wfConfig::set('scansEnabled_heartbleed', 1);
        }
        if (wfConfig::get('cacheType') == 'php' || wfConfig::get('cacheType') == 'falcon') {
            wfCache::removeCacheDirectoryHtaccess();
        }
        // IPv6 schema changes for 6.0.1
        $tables_with_ips = array('wfCrawlers', 'wfBadLeechers', 'wfBlockedIPLog', 'wfBlocks', 'wfHits', 'wfLeechers', 'wfLockedOut', 'wfLocs', 'wfLogins', 'wfReverseCache', 'wfScanners', 'wfThrottleLog', 'wfVulnScanners');
        foreach ($tables_with_ips as $ip_table) {
            $result = $wpdb->get_row("SHOW FIELDS FROM {$prefix}{$ip_table} where field = 'IP'");
            if (!$result || strtolower($result->Type) == 'binary(16)') {
                continue;
            }
            $db->queryWriteIgnoreError("ALTER TABLE {$prefix}{$ip_table} MODIFY IP BINARY(16)");
            // Just to be sure we don't corrupt the data if the alter fails.
            $result = $wpdb->get_row("SHOW FIELDS FROM {$prefix}{$ip_table} where field = 'IP'");
            if (!$result || strtolower($result->Type) != 'binary(16)') {
                continue;
            }
            $db->queryWriteIgnoreError("UPDATE {$prefix}{$ip_table} SET IP = CONCAT(LPAD(CHAR(0xff, 0xff), 12, CHAR(0)), LPAD(\n\tCHAR(\n\t\tCAST(IP as UNSIGNED) >> 24 & 0xFF,\n\t\tCAST(IP as UNSIGNED) >> 16 & 0xFF,\n\t\tCAST(IP as UNSIGNED) >> 8 & 0xFF,\n\t\tCAST(IP as UNSIGNED) & 0xFF\n\t),\n\t4,\n\tCHAR(0)\n))");
        }
        // Fix the data in the country column.
        // TODO: add version check so this doesn't run on every update.
        $ip_results = $wpdb->get_results("SELECT * FROM `{$prefix}wfBlockedIPLog` GROUP BY IP");
        if ($ip_results) {
            foreach ($ip_results as $ip_row) {
                $wpdb->query($wpdb->prepare("UPDATE `{$prefix}wfBlockedIPLog` SET countryCode = %s WHERE IP = %s", wfUtils::IP2Country(wfUtils::inet_ntop($ip_row->IP)), $ip_row->IP));
            }
        }
        if (wfConfig::get('other_hideWPVersion')) {
            wfUtils::hideReadme();
        }
        $colsFor610 = array('attackLogTime' => '`attackLogTime` double(17,6) unsigned NOT NULL AFTER `id`', 'statusCode' => '`statusCode` int(11) NOT NULL DEFAULT 0 AFTER `jsRun`', 'action' => "`action` varchar(64) NOT NULL DEFAULT '' AFTER `UA`", 'actionDescription' => '`actionDescription` text AFTER `action`', 'actionData' => '`actionData` text AFTER `actionDescription`');
        $hitTable = $wpdb->base_prefix . 'wfHits';
        foreach ($colsFor610 as $col => $colDefintion) {
            $count = $wpdb->get_col($wpdb->prepare(<<<SQL
SELECT * FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA=DATABASE()
AND COLUMN_NAME=%s
AND TABLE_NAME=%s
SQL
, $col, $hitTable));
            if (!$count) {
                $wpdb->query("ALTER TABLE {$hitTable} ADD COLUMN {$colDefintion}");
            }
        }
        $has404 = $wpdb->get_col($wpdb->prepare(<<<SQL
SELECT * FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA=DATABASE()
AND COLUMN_NAME='is404'
AND TABLE_NAME=%s
SQL
, $hitTable));
        if ($has404) {
            $wpdb->query(<<<SQL
UPDATE {$hitTable}
SET statusCode= CASE
WHEN is404=1 THEN 404
ELSE 200
END
SQL
);
            $wpdb->query("ALTER TABLE {$hitTable} DROP COLUMN `is404`");
        }
        $loginsTable = "{$wpdb->base_prefix}wfLogins";
        $hasHitID = $wpdb->get_col($wpdb->prepare(<<<SQL
SELECT * FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA=DATABASE()
AND COLUMN_NAME='hitID'
AND TABLE_NAME=%s
SQL
, $loginsTable));
        if (!$hasHitID) {
            $wpdb->query("ALTER TABLE {$loginsTable} ADD COLUMN hitID int(11) DEFAULT NULL AFTER `id`, ADD INDEX(hitID)");
        }
        if (!WFWAF_SUBDIRECTORY_INSTALL) {
            try {
                wfWAF::getInstance()->getStorageEngine()->setConfig('wafDisabled', false);
            } catch (wfWAFStorageFileException $e) {
                error_log($e);
            }
        }
        // Call this before creating the index in cases where the wp-cron isn't running.
        self::trimWfHits();
        $hitsTable = "{$wpdb->base_prefix}wfHits";
        $hasAttackLogTimeIndex = $wpdb->get_var($wpdb->prepare(<<<SQL
SELECT COLUMN_KEY FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = %s
AND COLUMN_NAME = 'attackLogTime'
SQL
, $hitsTable));
        if (!$hasAttackLogTimeIndex) {
            $wpdb->query("ALTER TABLE {$hitsTable} ADD INDEX `attackLogTime` (`attackLogTime`)");
        }
        //Must be the final line
    }
 public static function runInstall()
 {
     if (self::$runInstallCalled) {
         return;
     }
     self::$runInstallCalled = true;
     update_option('wordfence_version', WORDFENCE_VERSION);
     //In case we have a fatal error we don't want to keep running install.
     //EVERYTHING HERE MUST BE IDEMPOTENT
     //Remove old legacy cron job if exists
     wp_clear_scheduled_hook('wordfence_scheduled_scan');
     $restOfSite = wfConfig::get('cbl_restOfSiteBlocked', 'notset');
     if ($restOfSite == 'notset') {
         wfConfig::set('cbl_restOfSiteBlocked', '1');
     }
     $schema = new wfSchema();
     $schema->createAll();
     //if not exists
     wfConfig::setDefaults();
     //If not set
     //Install new schedule. If schedule config is blank it will install the default 'auto' schedule.
     wordfence::scheduleScans();
     if (wfConfig::get('autoUpdate') == '1') {
         wfConfig::enableAutoUpdate();
         //Sets up the cron
     }
     if (!wfConfig::get('apiKey')) {
         $api = new wfAPI('', wfUtils::getWPVersion());
         try {
             $keyData = $api->call('get_anon_api_key');
             if ($keyData['ok'] && $keyData['apiKey']) {
                 wfConfig::set('apiKey', $keyData['apiKey']);
             } else {
                 throw new Exception("Could not understand the response we received from the Wordfence servers when applying for a free API key.");
             }
         } catch (Exception $e) {
             error_log("Could not fetch free API key from Wordfence: " . $e->getMessage());
             return;
         }
     }
     wp_clear_scheduled_hook('wordfence_daily_cron');
     wp_clear_scheduled_hook('wordfence_hourly_cron');
     wp_schedule_event(time(), 'daily', 'wordfence_daily_cron');
     //'daily'
     wp_schedule_event(time(), 'hourly', 'wordfence_hourly_cron');
     $db = new wfDB();
     if ($db->columnExists('wfHits', 'HTTPHeaders')) {
         //Upgrade from 3.0.4
         global $wpdb;
         $prefix = $wpdb->base_prefix;
         $count = $db->querySingle("select count(*) as cnt from {$prefix}" . "wfHits");
         if ($count > 20000) {
             $db->queryWrite("delete from {$prefix}" . "wfHits order by id asc limit " . ($count - 20000));
         }
         $db->dropColumn('wfHits', 'HTTPHeaders');
     }
     //Upgrading from 1.5.6 or earlier needs:
     $db->createKeyIfNotExists('wfStatus', 'level', 'k2');
     if (wfConfig::get('isPaid') == 'free') {
         wfConfig::set('isPaid', '');
     }
     //End upgrade from 1.5.6
     global $wpdb;
     $prefix = $wpdb->base_prefix;
     $db->queryWriteIgnoreError("alter table {$prefix}" . "wfConfig modify column val longblob");
     $db->queryWriteIgnoreError("alter table {$prefix}" . "wfBlocks add column permanent tinyint UNSIGNED default 0");
     $db->queryWriteIgnoreError("alter table {$prefix}" . "wfStatus modify column msg varchar(1000) NOT NULL");
     //3.1.2 to 3.1.4
     $db->queryWriteIgnoreError("alter table {$prefix}" . "wfBlocks modify column blockedTime bigint signed NOT NULL");
     //3.2.1 to 3.2.2
     $db->queryWriteIgnoreError("alter table {$prefix}" . "wfLockedOut modify column blockedTime bigint signed NOT NULL");
     $db->queryWriteIgnoreError("drop table if exists {$prefix}" . "wfFileQueue");
     $db->queryWriteIgnoreError("drop table if exists {$prefix}" . "wfFileChanges");
     $optScanEnabled = $db->querySingle("select val from {$prefix}" . "wfConfig where name='scansEnabled_options'");
     if ($optScanEnabled != '0' && $optScanEnabled != '1') {
         $db->queryWrite("update {$prefix}" . "wfConfig set val='1' where name='scansEnabled_options'");
     }
     $optScanEnabled = $db->querySingle("select val from {$prefix}" . "wfConfig where name='scansEnabled_heartbleed'");
     if ($optScanEnabled != '0' && $optScanEnabled != '1') {
         //Enable heartbleed if no value is set.
         wfConfig::set('scansEnabled_heartbleed', 1);
     }
     //Must be the final line
 }