Plugin Directory

Changeset 2452411


Ignore:
Timestamp:
01/08/2021 10:04:19 AM (5 years ago)
Author:
ethicalhack3r
Message:

New 1.14 version release

Location:
wpscan
Files:
20 added
10 deleted
30 edited
1 copied

Legend:

Unmodified
Added
Removed
  • wpscan/tags/1.14/app/Account.php

    r2429586 r2452411  
    2525        $this->parent = $parent;
    2626
    27         add_action( 'wpscan/api/get/after', array( $this, 'update_account_status' ), 10, 2 );
    2827        add_action( 'admin_init', array( $this, 'add_account_summary_meta_box' ) );
    2928    }
    3029
    3130    /**
    32      * Update account status after the api request.
     31     * Update account status by calling the /status endpoint.
    3332     *
    3433     * @since 1.0.0
    35      * @param string $endpoint endpoint.
    36      * @param string $response response.
     34     * @param string $api_token
    3735     * @access public
    3836     * @return void
    3937     */
    40     public function update_account_status( $endpoint, $response ) {
    41         $wp_endpoit = '/wordpresses/' . str_replace( '.', '', get_bloginfo( 'version' ) );
     38    public function update_account_status( $api_token = null ) {
     39        $current = get_option( $this->parent->OPT_ACCOUNT_STATUS, array() );
     40        $updated = $current;
     41       
     42        $req = $this->parent->api_get( '/status', $api_token );
     43       
     44        if ( is_object( $req ) ) {
     45            $updated['plan'] = $req->plan;
    4246
    43         if ( $endpoint === $wp_endpoit ) {
    44             $current = get_option( $this->parent->OPT_ACCOUNT_STATUS, array() );
    45             $updated = $current;
    46 
    47             $updated['limit']     = wp_remote_retrieve_header( $response, 'x-ratelimit-limit' );
    48             $updated['remaining'] = wp_remote_retrieve_header( $response, 'x-ratelimit-remaining' );
    49             $updated['reset']     = wp_remote_retrieve_header( $response, 'x-ratelimit-reset' );
    50 
    51             if ( ! isset( $current['plan'] ) || $current['limit'] !== $updated['limit'] ) {
    52                 $req = $this->parent->api_get( '/status' );
    53 
    54                 // Plan.
    55                 if ( is_object( $req ) ) {
    56                     $updated['plan'] = $req->plan;
    57                 }
    58 
    59                 // For enterprise users.
    60                 if ( -1 === $req->requests_remaining ) {
    61                     $updated['limit']     = __( 'unlimited', 'wpscan' );
    62                     $updated['remaining'] = __( 'unlimited', 'wpscan' );
    63                     $updated['reset']     = __( 'unlimited', 'wpscan' );
    64                 }
     47            // Enterprise users.
     48            if ( -1 === $req->requests_remaining ) {
     49                $updated['limit']     = __( 'unlimited', 'wpscan' );
     50                $updated['remaining'] = __( 'unlimited', 'wpscan' );
     51                $updated['reset']     = __( 'unlimited', 'wpscan' );
     52            } else {
     53                $updated['limit']     = $req->requests_limit;
     54                $updated['remaining'] = $req->requests_remaining;
     55                $updated['reset']     = $req->requests_reset;
    6556            }
    6657
     
    9889    public function get_account_status() {
    9990        $defaults = array(
    100             'plan'      => 'NO DATA',
     91            'plan'      => 'None',
    10192            'limit'     => 50,
    10293            'remaining' => 50,
  • wpscan/tags/1.14/app/Checks/Check.php

    r2429586 r2452411  
    112112    final public function add_vulnerability( $title, $severity, $id ) {
    113113        $vulnerability = array(
    114             'id'       => $id,
    115114            'title'    => $title,
    116115            'severity' => $severity,
     116            'id'       => $id,
    117117        );
    118118
     
    220220        if ( is_array( $this->vulnerabilities ) ) {
    221221            $updated['security-checks'][ $this->id ]['vulnerabilities'] = $this->vulnerabilities;
     222
     223            $this->parent->maybe_fire_issue_found_action('security-check', $this->id, $updated['security-checks'][ $this->id ]);
    222224        } else {
    223225            $updated['security-checks'][ $this->id ]['vulnerabilities'] = array();
  • wpscan/tags/1.14/app/Checks/System.php

    r2429586 r2452411  
    1414 */
    1515class System {
     16
     17    public $OPT_FATAL_ERRORS = 'wpscan_fatal_errors';
     18
     19
    1620    /**
    1721     * A list of registered checks.
     
    3539    public function __construct( $parent ) {
    3640        $this->parent = $parent;
     41
     42        register_shutdown_function( array( $this, 'catch_errors' ) );
     43
     44        add_action( 'admin_notices', array( $this, 'display_errors' ) );
    3745
    3846        add_action( 'plugins_loaded', array( $this, 'load_checks' ) );
     
    8694
    8795    /**
     96     * Register a shutdown hook to catch errors
     97     *
     98     * @since 1.0.0
     99     * @access public
     100     * @return void
     101     */
     102    public function catch_errors() {
     103        $error = error_get_last();
     104
     105        if ($error && $error['type']) {
     106           
     107            if ( basename($error['file']) == 'check.php' ) {
     108                $errors = get_option($this->OPT_FATAL_ERRORS, array() );
     109               
     110                array_push( $errors, $error );
     111
     112                update_option( $this->OPT_FATAL_ERRORS, array_unique( $errors ) );
     113
     114                $report = $this->parent->get_report();
     115
     116                $report['cache'] = strtotime( current_time( 'mysql' ) );
     117
     118                update_option( $this->parent->OPT_REPORT, $report );
     119
     120                $this->parent->classes['account']->update_account_status();
     121
     122                delete_transient( $this->parent->WPSCAN_TRANSIENT_CRON );
     123            }
     124        }   
     125    }
     126
     127    /**
     128     * Display fatal errors
     129     *
     130     * @since 1.0.0
     131     * @access public
     132     * @return void
     133     */
     134    public function display_errors() {
     135        $screen = get_current_screen();
     136        $errors = get_option($this->OPT_FATAL_ERRORS, array() );
     137       
     138
     139        if ( strstr( $screen->id, $this->parent->classes['report']->page ) ) {
     140            foreach ($errors as $err ) {
     141                $msg = explode('Stack', $err['message'])[0];
     142                $msg = trim($msg);
     143
     144                echo "<div class='notice notice-error'><p>$msg</p></div>";
     145            }
     146        }
     147    }
     148
     149    /**
    88150     * List vulnerabilities in the report.
    89151     *
  • wpscan/tags/1.14/app/Dashboard.php

    r2429586 r2452411  
    7676
    7777        foreach ( $vulns as $vuln ) {
    78             echo "<div><span class='dashicons dashicons-warning is-red'></span>&nbsp; " . esc_html($vuln) . "</div><br/>";
     78            $vuln = wp_kses( $vuln, array( 'a' => array( 'href' => array() ) ) ); // Only allow a href HTML tags.
     79            echo "<div><span class='dashicons dashicons-warning is-red'></span>&nbsp; " . $vuln . "</div><br/>";
    7980        }
    8081
  • wpscan/tags/1.14/app/Notification.php

    r2429586 r2452411  
    8080     */
    8181    public function add_meta_box_notification() {
     82        if ( $this->parent->is_wp_cron_disabled() ) {
     83            return;
     84        }
     85
    8286        add_meta_box(
    8387            'wpscan-metabox-notification',
  • wpscan/tags/1.14/app/Plugin.php

    r2429586 r2452411  
    5656    public $report;
    5757
     58    // Action fired when an issue is found
     59    public $WPSCAN_ISSUE_FOUND = 'wpscan_issue_found';
     60
    5861    /**
    5962     * Class constructor.
     
    7982        add_action( 'admin_bar_menu', array( $this, 'admin_bar' ), 65 );
    8083        add_action( $this->WPSCAN_SCHEDULE, array( $this, 'check_now' ) );
     84        add_action( 'in_admin_header', array( $this, 'deactivate_screen' ) );
     85
     86        // Check if wp cron is disabled
     87        if ( $this->is_wp_cron_disabled() ) {
     88            add_action( 'admin_notices', array( $this, 'wp_cron_alert' ) );
     89        }
    8190
    8291        if ( defined( 'WPSCAN_API_TOKEN' ) ) {
     
    129138     */
    130139    public function deactivate() {
     140        delete_option( $this->OPT_SCANNING_INTERVAL );
     141
     142        delete_option( $this->OPT_SCANNING_TIME );
     143
    131144        wp_clear_scheduled_hook( $this->WPSCAN_SCHEDULE );
     145    }
     146
     147    /**
     148     * Deactivate screen
     149     *
     150     * @since 1.14.0
     151     * @access public
     152     * @return void
     153     */
     154    public function deactivate_screen() {
     155        global $pagenow;
     156
     157        if ( 'plugins.php' === $pagenow ) {
     158            include_once plugin_dir_path( WPSCAN_PLUGIN_FILE ) . 'views/deactivate.php';
     159        }
     160    }
     161
     162    /**
     163     * Check if WP-Cron is disabled
     164     *
     165     * @since 1.14.0
     166     * @access public
     167     * @return bool
     168     */
     169    public function is_wp_cron_disabled() {
     170        return defined('DISABLE_WP_CRON') && DISABLE_WP_CRON;
     171    }
     172
     173    /**
     174     * Display cron disabled alert
     175     *
     176     * @since 1.14.0
     177     * @access public
     178     * @return void
     179     */
     180    public function wp_cron_alert() {
     181        echo "<div class='notice notice-error'><p>". __( 'WP-Cron has been disabled in the wp-config.php file using the <code>DISABLE_WP_CRON</code> constant. Automated scans and other features that rely on cron will not work.', 'wpscan' ) ."</p></div>";
    132182    }
    133183
     
    161211     */
    162212    public function admin_enqueue( $hook ) {
     213        global $pagenow;
    163214        $screen = get_current_screen();
    164215
     
    207258
    208259            wp_localize_script('wpscan', 'wpscan', $localized);
     260        }
     261
     262        if ( 'plugins.php' === $pagenow ) {
     263            wp_enqueue_style(
     264                'wpscan-deactivate',
     265                plugins_url( 'assets/css/deactivate.css', WPSCAN_PLUGIN_FILE ),
     266                array(),
     267                $this->wpscan_plugin_version()
     268            );
     269
     270            wp_enqueue_script(
     271                'wpscan-deactivate',
     272                plugins_url( 'assets/js/deactivate.js', WPSCAN_PLUGIN_FILE ),
     273                    array( 'jquery' ),
     274                    $this->wpscan_plugin_version()
     275            );
    209276        }
    210277    }
     
    387454
    388455        // Hook before the request.
    389         do_action( 'wpscan/api/get/before', $endpoint );
     456        //do_action( 'wpscan/api/get/before', $endpoint );
    390457
    391458        // Start the request.
     
    394461
    395462        // Hook after the request.
    396         do_action( 'wpscan/api/get/after', $endpoint, $response );
     463        //do_action( 'wpscan/api/get/after', $endpoint, $response );
    397464
    398465        if ( 200 === $code ) {
     
    479546        // Reset errors.
    480547        update_option( $this->OPT_ERRORS, array() );
     548        update_option( $this->classes['checks/system']->OPT_FATAL_ERRORS, array() );
    481549
    482550        // Plugins.
    483         $report['plugins'] = $this->verify_plugins( $ignored['plugins'] );
     551        $this->report['plugins'] = $this->verify_plugins( $ignored['plugins'] );
    484552
    485553        // Themes.
    486         $report['themes'] = $this->verify_themes( $ignored['themes'] );
     554        $this->report['themes'] = $this->verify_themes( $ignored['themes'] );
    487555
    488556        // WordPress.
    489557        if ( ! isset( $ignored['wordpress'] ) ) {
    490             $report['wordpress'] = $this->verify_wordpress();
     558            $this->report['wordpress'] = $this->verify_wordpress();
    491559        } else {
    492             $report['wordpress'] = array();
     560            $this->report['wordpress'] = array();
    493561        }
    494562
    495563        // Security checks.
    496         $report['security-checks'] = array();
     564        $this->report['security-checks'] = array();
    497565
    498566        foreach ( $this->classes['checks/system']->checks as $id => $data ) {
    499567            $data['instance']->perform();
    500             $report['security-checks'][ $id ]['vulnerabilities'] = array();
     568            $this->report['security-checks'][ $id ]['vulnerabilities'] = array();
    501569
    502570            if ( $data['instance']->vulnerabilities ) {
    503                 $report['security-checks'][ $id ]['vulnerabilities'] = $data['instance']->get_vulnerabilities();
     571                $this->report['security-checks'][ $id ]['vulnerabilities'] = $data['instance']->get_vulnerabilities();
     572
     573                $this->maybe_fire_issue_found_action('security-check', $id, $this->report['security-checks'][ $id ]);
    504574            }
    505575        }
    506576
    507577        // Caching.
    508         $report['cache'] = strtotime( current_time( 'mysql' ) );
     578        $this->report['cache'] = strtotime( current_time( 'mysql' ) );
    509579
    510580        // Saving.
    511         update_option( $this->OPT_REPORT, $report, true );
     581        update_option( $this->OPT_REPORT, $this->report, true );
     582
     583        // Updates account status (API calls etc).
     584        $this->classes['account']->update_account_status();
     585    }
     586
     587    /**
     588    * Fires the wpscan_issue_found action if needed
     589    *
     590    * @since 1.14.0
     591    *
     592    * @param string $type - The affected component type: plugin, theme, wordpress or security-check
     593    * @param string $slug - The affected component slug.
     594    *                       For wordpress, it will be the version (ie 5.5.3)
     595    *                       For security-checks, it will be the id of the check, ie xmlrpc-enabled
     596    * @param array $details - An array containing some keys, such as vulnerabilities
     597    * @param array additional_details - An array with the plugin details, such as Version etc
     598    **/
     599    public function maybe_fire_issue_found_action($type, $slug, $details, $additional_details = []) {
     600        if ( !count($details['vulnerabilities']) > 0) {
     601            return;
     602        }
     603
     604        do_action($this->WPSCAN_ISSUE_FOUND, $type, $slug, $details, $additional_details);
    512605    }
    513606
     
    546639                    $plugins[ $slug ]['closed'] = false;
    547640                }
     641
     642                $this->maybe_fire_issue_found_action('plugin', $slug, $plugins[ $slug ], $details );
    548643            } else {
    549644                if ( 404 === $result ) {
     
    596691                    $themes[ $slug ]['closed'] = false;
    597692                }
     693
     694                $this->maybe_fire_issue_found_action('theme', $slug, $themes[ $slug ], $details );
    598695            } else {
    599696                if ( 404 === $result ) {
     
    614711     */
    615712    public function verify_wordpress() {
    616         $wordperss = array();
     713        $wordpress = array();
    617714
    618715        $version = get_bloginfo( 'version' );
     
    620717
    621718        if ( is_object( $result ) ) {
    622             $wordperss[ $version ]['vulnerabilities'] = $this->get_vulnerabilities( $result, $version );
    623         }
    624 
    625         return $wordperss;
     719            $wordpress[ $version ]['vulnerabilities'] = $this->get_vulnerabilities( $result, $version );
     720
     721            $this->maybe_fire_issue_found_action('wordpress', $version, $wordpress[ $version ] );
     722        }
     723
     724        return $wordpress;
    626725    }
    627726
     
    812911     */
    813912    public function delete_doing_cron_transient() {
    814         $option = get_option( '_transient_wpscan_doing_cron' );
    815 
    816         if ( $option ) {
    817             delete_option( '_transient_wpscan_doing_cron' );
    818         }
     913        delete_transient( $this->WPSCAN_TRANSIENT_CRON );
    819914    }
    820915}
  • wpscan/tags/1.14/app/Report.php

    r2429586 r2452411  
    1616{
    1717    // Page slug.
    18     private $page;
     18    public $page;
    1919
    2020    /**
  • wpscan/tags/1.14/app/Settings.php

    r2429586 r2452411  
    2929        add_action( 'admin_init', array( $this, 'admin_init' ) );
    3030        add_action( 'admin_notices', array( $this, 'got_api_token' ) );
    31 
    3231        add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue' ) );
    3332
    34         add_action( 'add_option_' . $this->parent->OPT_SCANNING_INTERVAL, array( $this, 'schedule_event' ), 10, 2 );
    35         add_action( 'update_option_' . $this->parent->OPT_SCANNING_INTERVAL, array( $this, 'schedule_event' ), 10, 3 );
    36         add_action( 'update_option_' . $this->parent->OPT_SCANNING_TIME, array( $this, 'schedule_event' ), 10, 3 );
    37 
    38         add_action( 'update_option_' . $this->parent->OPT_IGNORE_ITEMS, array( $this, 'update_ignored_items' ), 10, 3 );
     33        if ( ! $this->parent->is_wp_cron_disabled() ) {
     34            add_action( 'add_option_' . $this->parent->OPT_SCANNING_INTERVAL, array( $this, 'schedule_event' ), 10, 2 );
     35            add_action( 'update_option_' . $this->parent->OPT_SCANNING_INTERVAL, array( $this, 'schedule_event' ), 10, 2 );
     36            add_action( 'update_option_' . $this->parent->OPT_SCANNING_TIME, array( $this, 'schedule_event' ), 10, 2 );
     37        }
     38
     39        add_action( 'update_option_' . $this->parent->OPT_IGNORE_ITEMS, array( $this, 'update_ignored_items' ), 10, 2 );
    3940    }
    4041
     
    6263                'wpscan-settings',
    6364                plugins_url( 'assets/css/settings.css', WPSCAN_PLUGIN_FILE ),
    64                 array(),
    65                 $this->parent->wpscan_plugin_version()
     65                    array(),
     66                    $this->parent->wpscan_plugin_version()
    6667            );
    6768        }
     
    7677     */
    7778    public function admin_init() {
    78         register_setting( $this->page, $this->parent->OPT_API_TOKEN, array( $this, 'sanitize_api_token' ) );
    79         register_setting( $this->page, $this->parent->OPT_SCANNING_INTERVAL, 'sanitize_text_field' );
    80         register_setting( $this->page, $this->parent->OPT_SCANNING_TIME, 'sanitize_text_field' );
     79        // No need to sanitise the API token from the Settings form if we are using the token from the
     80        // WPSCAN_API_TOKEN constant. register_setting() is run before WPSCAN_API_TOKEN is placed in the database,
     81        // causing a NULL API token to be passed to some functions if called when using a WPSCAN_API_TOKEN constant.
     82        if ( ! defined( 'WPSCAN_API_TOKEN' ) ) {
     83            register_setting( $this->page, $this->parent->OPT_API_TOKEN, array( 'sanitize_callback' => array( $this, 'sanitize_api_token' ) ) );
     84        }
     85
    8186        register_setting( $this->page, $this->parent->OPT_IGNORE_ITEMS );
     87
     88        if ( ! $this->parent->is_wp_cron_disabled() ) {
     89            register_setting( $this->page, $this->parent->OPT_SCANNING_INTERVAL, 'sanitize_text_field' );
     90            register_setting( $this->page, $this->parent->OPT_SCANNING_TIME, 'sanitize_text_field' );
     91        }
    8292
    8393        $section = $this->page . '_section';
     
    98108        );
    99109
    100         add_settings_field(
    101             $this->parent->OPT_SCANNING_INTERVAL,
    102             __( 'Automated Scanning', 'wpscan' ),
    103             array( $this, 'field_scanning_interval' ),
    104             $this->page,
    105             $section
    106         );
    107 
    108         add_settings_field(
    109             $this->parent->OPT_SCANNING_TIME,
    110             __( 'Scanning Time', 'wpscan' ),
    111             array( $this, 'field_scanning_time' ),
    112             $this->page,
    113             $section
    114         );
     110        if ( ! $this->parent->is_wp_cron_disabled() ) {
     111
     112            add_settings_field(
     113                $this->parent->OPT_SCANNING_INTERVAL,
     114                __( 'Automated Scanning', 'wpscan' ),
     115                array( $this, 'field_scanning_interval' ),
     116                $this->page,
     117                $section
     118            );
     119
     120            add_settings_field(
     121                $this->parent->OPT_SCANNING_TIME,
     122                __( 'Scanning Time', 'wpscan' ),
     123                array( $this, 'field_scanning_time' ),
     124                $this->page,
     125                $section
     126            );
     127
     128        }
    115129
    116130        add_settings_field(
     
    210224            echo '</form>';
    211225        echo '</div>';
    212   }
     226    }
    213227
    214228    /**
     
    302316    public function field_scanning_time() {
    303317        $opt      = $this->parent->OPT_SCANNING_TIME;
    304         $value    = esc_attr( get_option( $opt, '12:00' ) );
     318        $value    = esc_attr( get_option( $opt, date('H:i') ) );
    305319        $disabled = $this->parent->is_interval_scanning_disabled() ? "disabled='true'" : null;
    306320
     
    367381            : __( 'Plugins', 'wpscan' );
    368382
    369 
    370383        echo "<div class='wpscan-ignore-items-section'>";
    371384
     
    397410    public function sanitize_api_token( $value ) {
    398411        $value  = trim( $value );
    399         $result = $this->parent->api_get( '/status', $value );
     412
     413        // update_account_status() calls the /status API endpoint, verifying the validity of the Token passed via $value and updates the account status if needed.
     414        if ( empty( $value ) ) {
     415            delete_option( $this->parent->OPT_ACCOUNT_STATUS );
     416        } else {
     417            $this->parent->classes['account']->update_account_status( $value );
     418        }
    400419
    401420        $errors = get_option( $this->parent->OPT_ERRORS );
     
    432451        if ( ! empty( $api_token ) && $old_value !== $value ) {
    433452            $interval = esc_attr( get_option( $this->parent->OPT_SCANNING_INTERVAL, 'daily' ) );
    434             $time     = esc_attr( get_option( $this->parent->OPT_SCANNING_TIME, '12:00 +1day' ) );
     453            $time     = esc_attr( get_option( $this->parent->OPT_SCANNING_TIME, date('H:i') . ' +1day' ) );
    435454
    436455            wp_clear_scheduled_hook( $this->parent->WPSCAN_SCHEDULE );
  • wpscan/tags/1.14/app/Summary.php

    r2429586 r2452411  
    6767        ?>
    6868
     69        <?php
     70            if ( ! empty( $errors ) ) {
     71                foreach ( $errors as $err ) {
     72                    // $err should not contain user input. If you like to add an esc_html() here, be sure to update the error text that use HTML
     73                    echo '<p class="wpscan-summary-res is-red"><span class="dashicons dashicons-megaphone"></span> <strong>' . $err . '</strong></p>';
     74                }
     75            } elseif ( empty( $this->parent->get_report() ) ) { // No scan run yet.
     76                echo '<p class="wpscan-summary-res is-red"><span class="dashicons dashicons-megaphone"></span> <strong>' . __( 'No scan run yet!', 'wpscan' ) . '</strong></p>';
     77            } elseif ( empty( $errors ) && 0 === $total ) {
     78                echo '<p class="wpscan-summary-res is-green"><span class="dashicons dashicons-awards"></span> <strong>' . __( 'No known vulnerabilities found', 'wpscan' ) . '</strong></p>';
     79            } elseif( ! get_option( $this->parent->OPT_API_TOKEN ) ) {
     80                echo '<p class="wpscan-summary-res is-red"><span class="dashicons dashicons-megaphone"></span> <strong>' . __( 'You need to add a WPScan API Token to the settings page', 'wpscan' ) . '</strong></p>';
     81            } else {
     82                echo '<p class="wpscan-summary-res is-red"><span class="dashicons dashicons-megaphone"></span> <strong>' . __( 'Some vulnerabilities were found', 'wpscan' ) . '</strong></p>';
     83            }
     84        ?>
     85
    6986        <p>
    7087            <?php _e( 'The last full scan was run on: ', 'wpscan' ) ?>
     
    84101        </p>
    85102
    86             <?php
    87                 // Only show next scan time if there's a scheduled cron job.
    88                 if ( wp_next_scheduled( $this->parent->WPSCAN_SCHEDULE ) ) {
    89             ?>
     103            <?php if ( ! $this->parent->is_wp_cron_disabled() && wp_next_scheduled( $this->parent->WPSCAN_SCHEDULE ) ) { ?>
    90104                <p>
    91105                    <?php _e( 'The next scan will automatically be run on ', 'wpscan' ) ?>
     
    96110        <?php } ?>
    97111
    98         <?php
    99             if ( ! empty( $errors ) ) {
    100                 foreach ( $errors as $err ) {
    101                     // $err should not contain user input. If you like to add an esc_html() here, be sure to update the error text that use HTML
    102                     echo '<p class="wpscan-summary-res is-red"><span class="dashicons dashicons-megaphone"></span> <strong>' . $err . '</strong></p>';
     112        <p class="description">
     113            <?php
     114                if ( get_option( $this->parent->OPT_API_TOKEN ) ) {
     115                    _e( 'Click the Run All button to run a full vulnerability scan against your WordPress website.', 'wpscan' );
     116                } else {
     117                    _e( 'Add your API token to the settings page to be able to run a full scan.', 'wpscan' );
    103118                }
    104             } elseif ( empty( $this->parent->get_report() ) ) { // No scan run yet.
    105                 echo '<p class="wpscan-summary-res is-red"><span class="dashicons dashicons-megaphone"></span> <strong>' . __( 'No scan run yet!', 'wpscan' ) . '</strong></p>';
    106             } elseif ( empty( $errors ) && 0 === $total ) {
    107                 echo '<p class="wpscan-summary-res is-green"><span class="dashicons dashicons-awards"></span> <strong>' . __( 'No known vulnerabilities found', 'wpscan' ) . '</strong></p>';
    108             } elseif( ! get_option($this->parent->OPT_API_TOKEN) ) {
    109                 echo '<p class="wpscan-summary-res is-red"><span class="dashicons dashicons-megaphone"></span> <strong>' . __( 'You need to add a WPScan API Token to the settings page', 'wpscan' ) . '</strong></p>';
    110             } else {
    111                 echo '<p class="wpscan-summary-res is-red"><span class="dashicons dashicons-megaphone"></span> <strong>' . __( 'Some vulnerabilities were found', 'wpscan' ) . '</strong></p>';
    112             }
    113         ?>
    114 
    115         <p class="description">
    116             <?php _e( 'Click the Run All button to run a full vulnerability scan against your WordPress website.', 'wpscan' ) ?>
     119            ?>
    117120        </p>
    118121
  • wpscan/tags/1.14/assets/css/style.css

    r2417112 r2452411  
    1010  margin-bottom: 5px;
    1111  margin-right: 12px;
     12  white-space: normal !important;
     13}
     14
     15.column-name {
     16  word-break: break-word;
     17  width: 250px;
    1218}
    1319
  • wpscan/tags/1.14/assets/js/scripts.js

    r2424629 r2452411  
    3232      success: function( ) {
    3333        check_cron();
     34      },
     35      error: function () {
     36        location.reload();
    3437      }
    3538    } );
     
    5659        },
    5760        error: function ( ) {
    58           check_cron();
     61          location.reload();
    5962        }
    6063      } );
  • wpscan/tags/1.14/readme.txt

    r2433081 r2452411  
    33Tags: wpscan, wpvulndb, security, vulnerability, hack, scan, exploit, secure, alerts
    44Requires at least: 3.4
    5 Tested up to: 5.5.3
    6 Stable tag: 1.13.2
     5Tested up to: 5.6
     6Stable tag: 1.14
    77Requires PHP: 5.5
    88License: GPLv3
     
    48484. Save the API token to the WPScan settings page or within the wp-config.php file
    4949
    50 == FAQ ==
     50== Frequently Asked Questions ==
    5151
    52 * How many API calls are made?
     52= How many API calls are made? =
    5353
    5454  There is one API call made for the WordPress version, one call for each installed plugin and one for each theme. By default there is one scan per day. The number of daily scans can be configured when configuring notifications.
    5555
    56 * How can I configure the API token in the wp-config.php file?
     56= How can I configure the API token in the wp-config.php file? =
    5757
    5858  To configure your API token in the wp-config.php file, use the following PHP code: `define( 'WPSCAN_API_TOKEN', '$your_api_token' );`
    5959
    60 * How do I disable vulnerability scanning altogether?
     60= How do I disable vulnerability scanning altogether? =
    6161
    6262  You can set the following PHP constant in the wp-config.php file to disable scanning; `define( 'WPSCAN_DISABLE_SCANNING_INTERVAL', true );`.
    6363
    64 * Why is the "Summary" section and the "Run All" button not showing?
     64= Why is the "Summary" section and the "Run All" button not showing? =
    6565
    6666  The cron job did not run, which can be due to:
     
    7878
    7979== Changelog ==
     80
     81= 1.14 =
     82
     83* Uses the status endpoint to get account data
     84* Fixes the account status not being updated unless a scan is performed when the API token is updated/set
     85* Adds vulnerability found hook
     86* New security check: Check for weak user passwords
     87* New security check: HTTPS
     88* Clear plan info if API Token set to null
     89* Fixes automated scanning when plugin deactivated and reactivated
     90* Fixes cron job not being created when using the WPSCAN_API_TOKEN constant
     91* Change default scanning time to the current time
     92* Many other small improvements
    8093
    8194= 1.13.2 =
  • wpscan/tags/1.14/security-checks/xmlrpc-enabled/check.php

    r2433081 r2452411  
    7676        } else {
    7777            if ( preg_match( '/<string>Incorrect username or password.<\/string>/', $authenticated_response['body'] ) ) {
    78                 $this->add_vulnerability( __( 'The XML-RPC interface is enabled. This significantly increases your site\'s attack surface.', 'wpscan' ), 'medium', sanitize_title( $url ) );
     78                $this->add_vulnerability( __( 'The XML-RPC interface is enabled. This significantly increases your site\'s attack surface', 'wpscan' ), 'medium', sanitize_title( $url ) );
    7979                return;
    8080            } else {
     
    8484
    8585                if ( preg_match( '/<string>Hello!<\/string>/', $unauthenticated_response['body'] ) ) {
    86                     $this->add_vulnerability( __( 'The XML-RPC interface is partly disabled, but still allows unauthenticated requests.', 'wpscan' ), 'low', sanitize_title( $url ) );
     86                    $this->add_vulnerability( __( 'The XML-RPC interface is partly disabled, but still allows unauthenticated requests', 'wpscan' ), 'low', sanitize_title( $url ) );
    8787                }
    8888            }
  • wpscan/tags/1.14/views/report.php

    r2429586 r2452411  
    88
    99<div class="wrap">
    10   <?php echo file_get_contents($this->parent->plugin_dir. 'assets/svg/logo.svg'); ?>
     10  <h1>
     11    <?php echo file_get_contents($this->parent->plugin_dir. 'assets/svg/logo.svg'); ?>
     12  </h1>
    1113 
    1214  <hr class="wp-header-end">
     
    4143              <tr>
    4244                <td scope="col" class="manage-column check-column">&nbsp;</td>
    43                 <th scope="col" class="manage-column column-name column-primary" width="250"><?php _e( 'Name', 'wpscan' ) ?></th>
     45                <th scope="col" class="manage-column column-name column-primary"><?php _e( 'Name', 'wpscan' ) ?></th>
    4446                <th scope="col" class="manage-column column-description"><?php _e( 'Vulnerabilities', 'wpscan' ) ?></th>
    4547              </tr>
     
    7678                <tr>
    7779                  <td scope="col" class="manage-column check-column">&nbsp;</td>
    78                   <th scope="col" class="manage-column column-name column-primary" width="250"><?php _e( 'Name', 'wpscan' ) ?></th>
     80                  <th scope="col" class="manage-column column-name column-primary"><?php _e( 'Name', 'wpscan' ) ?></th>
    7981                  <th scope="col" class="manage-column column-description"><?php _e( 'Vulnerabilities', 'wpscan' ) ?></th>
    8082                </tr>
     
    8385                <?php
    8486                  foreach ( get_plugins() as $name => $details ) {
    85                     $slug = $this->parent->get_plugin_slug( $name, $details );
     87                    $slug      = $this->parent->get_plugin_slug( $name, $details );
    8688                    $is_closed = $this->is_item_closed('plugins', $slug);
    8789                ?>
     
    124126                <tr>
    125127                  <td scope="col" class="manage-column check-column">&nbsp;</td>
    126                   <th scope="col" class="manage-column column-name column-primary" width="250"><?php _e( 'Name', 'wpscan' ) ?></th>
     128                  <th scope="col" class="manage-column column-name column-primary"><?php _e( 'Name', 'wpscan' ) ?></th>
    127129                  <th scope="col" class="manage-column column-description"><?php _e( 'Vulnerabilities', 'wpscan' ) ?></th>
    128130                </tr>
     
    168170                    <tr>
    169171                        <td scope="col" class="manage-column check-column"></td>
    170                         <th scope="col" class="manage-column column-name column-primary" width="250"><?php _e('Name', 'wpscan') ?></th>
     172                        <th scope="col" class="manage-column column-name column-primary"><?php _e('Name', 'wpscan') ?></th>
    171173                        <th scope="col" class="manage-column column-description"><?php _e('Result', 'wpscan') ?></th>
    172174                        <th scope="col" class="manage-column column-description"><?php _e('Actions', 'wpscan') ?></th>
  • wpscan/tags/1.14/wpscan.php

    r2433081 r2452411  
    44 * Plugin URI:    http://wordpress.org/plugins/wpscan/
    55 * Description:   WPScan WordPress Security Scanner. Scans your system for security vulnerabilities listed in the WPScan Vulnerability Database.
    6  * Version:       1.13.2
     6 * Version:       1.14
    77 * Author:        WPScan Team
    88 * Author URI:    https://wpscan.com/
  • wpscan/trunk/app/Account.php

    r2429586 r2452411  
    2525        $this->parent = $parent;
    2626
    27         add_action( 'wpscan/api/get/after', array( $this, 'update_account_status' ), 10, 2 );
    2827        add_action( 'admin_init', array( $this, 'add_account_summary_meta_box' ) );
    2928    }
    3029
    3130    /**
    32      * Update account status after the api request.
     31     * Update account status by calling the /status endpoint.
    3332     *
    3433     * @since 1.0.0
    35      * @param string $endpoint endpoint.
    36      * @param string $response response.
     34     * @param string $api_token
    3735     * @access public
    3836     * @return void
    3937     */
    40     public function update_account_status( $endpoint, $response ) {
    41         $wp_endpoit = '/wordpresses/' . str_replace( '.', '', get_bloginfo( 'version' ) );
     38    public function update_account_status( $api_token = null ) {
     39        $current = get_option( $this->parent->OPT_ACCOUNT_STATUS, array() );
     40        $updated = $current;
     41       
     42        $req = $this->parent->api_get( '/status', $api_token );
     43       
     44        if ( is_object( $req ) ) {
     45            $updated['plan'] = $req->plan;
    4246
    43         if ( $endpoint === $wp_endpoit ) {
    44             $current = get_option( $this->parent->OPT_ACCOUNT_STATUS, array() );
    45             $updated = $current;
    46 
    47             $updated['limit']     = wp_remote_retrieve_header( $response, 'x-ratelimit-limit' );
    48             $updated['remaining'] = wp_remote_retrieve_header( $response, 'x-ratelimit-remaining' );
    49             $updated['reset']     = wp_remote_retrieve_header( $response, 'x-ratelimit-reset' );
    50 
    51             if ( ! isset( $current['plan'] ) || $current['limit'] !== $updated['limit'] ) {
    52                 $req = $this->parent->api_get( '/status' );
    53 
    54                 // Plan.
    55                 if ( is_object( $req ) ) {
    56                     $updated['plan'] = $req->plan;
    57                 }
    58 
    59                 // For enterprise users.
    60                 if ( -1 === $req->requests_remaining ) {
    61                     $updated['limit']     = __( 'unlimited', 'wpscan' );
    62                     $updated['remaining'] = __( 'unlimited', 'wpscan' );
    63                     $updated['reset']     = __( 'unlimited', 'wpscan' );
    64                 }
     47            // Enterprise users.
     48            if ( -1 === $req->requests_remaining ) {
     49                $updated['limit']     = __( 'unlimited', 'wpscan' );
     50                $updated['remaining'] = __( 'unlimited', 'wpscan' );
     51                $updated['reset']     = __( 'unlimited', 'wpscan' );
     52            } else {
     53                $updated['limit']     = $req->requests_limit;
     54                $updated['remaining'] = $req->requests_remaining;
     55                $updated['reset']     = $req->requests_reset;
    6556            }
    6657
     
    9889    public function get_account_status() {
    9990        $defaults = array(
    100             'plan'      => 'NO DATA',
     91            'plan'      => 'None',
    10192            'limit'     => 50,
    10293            'remaining' => 50,
  • wpscan/trunk/app/Checks/Check.php

    r2429586 r2452411  
    112112    final public function add_vulnerability( $title, $severity, $id ) {
    113113        $vulnerability = array(
    114             'id'       => $id,
    115114            'title'    => $title,
    116115            'severity' => $severity,
     116            'id'       => $id,
    117117        );
    118118
     
    220220        if ( is_array( $this->vulnerabilities ) ) {
    221221            $updated['security-checks'][ $this->id ]['vulnerabilities'] = $this->vulnerabilities;
     222
     223            $this->parent->maybe_fire_issue_found_action('security-check', $this->id, $updated['security-checks'][ $this->id ]);
    222224        } else {
    223225            $updated['security-checks'][ $this->id ]['vulnerabilities'] = array();
  • wpscan/trunk/app/Checks/System.php

    r2429586 r2452411  
    1414 */
    1515class System {
     16
     17    public $OPT_FATAL_ERRORS = 'wpscan_fatal_errors';
     18
     19
    1620    /**
    1721     * A list of registered checks.
     
    3539    public function __construct( $parent ) {
    3640        $this->parent = $parent;
     41
     42        register_shutdown_function( array( $this, 'catch_errors' ) );
     43
     44        add_action( 'admin_notices', array( $this, 'display_errors' ) );
    3745
    3846        add_action( 'plugins_loaded', array( $this, 'load_checks' ) );
     
    8694
    8795    /**
     96     * Register a shutdown hook to catch errors
     97     *
     98     * @since 1.0.0
     99     * @access public
     100     * @return void
     101     */
     102    public function catch_errors() {
     103        $error = error_get_last();
     104
     105        if ($error && $error['type']) {
     106           
     107            if ( basename($error['file']) == 'check.php' ) {
     108                $errors = get_option($this->OPT_FATAL_ERRORS, array() );
     109               
     110                array_push( $errors, $error );
     111
     112                update_option( $this->OPT_FATAL_ERRORS, array_unique( $errors ) );
     113
     114                $report = $this->parent->get_report();
     115
     116                $report['cache'] = strtotime( current_time( 'mysql' ) );
     117
     118                update_option( $this->parent->OPT_REPORT, $report );
     119
     120                $this->parent->classes['account']->update_account_status();
     121
     122                delete_transient( $this->parent->WPSCAN_TRANSIENT_CRON );
     123            }
     124        }   
     125    }
     126
     127    /**
     128     * Display fatal errors
     129     *
     130     * @since 1.0.0
     131     * @access public
     132     * @return void
     133     */
     134    public function display_errors() {
     135        $screen = get_current_screen();
     136        $errors = get_option($this->OPT_FATAL_ERRORS, array() );
     137       
     138
     139        if ( strstr( $screen->id, $this->parent->classes['report']->page ) ) {
     140            foreach ($errors as $err ) {
     141                $msg = explode('Stack', $err['message'])[0];
     142                $msg = trim($msg);
     143
     144                echo "<div class='notice notice-error'><p>$msg</p></div>";
     145            }
     146        }
     147    }
     148
     149    /**
    88150     * List vulnerabilities in the report.
    89151     *
  • wpscan/trunk/app/Dashboard.php

    r2429586 r2452411  
    7676
    7777        foreach ( $vulns as $vuln ) {
    78             echo "<div><span class='dashicons dashicons-warning is-red'></span>&nbsp; " . esc_html($vuln) . "</div><br/>";
     78            $vuln = wp_kses( $vuln, array( 'a' => array( 'href' => array() ) ) ); // Only allow a href HTML tags.
     79            echo "<div><span class='dashicons dashicons-warning is-red'></span>&nbsp; " . $vuln . "</div><br/>";
    7980        }
    8081
  • wpscan/trunk/app/Notification.php

    r2429586 r2452411  
    8080     */
    8181    public function add_meta_box_notification() {
     82        if ( $this->parent->is_wp_cron_disabled() ) {
     83            return;
     84        }
     85
    8286        add_meta_box(
    8387            'wpscan-metabox-notification',
  • wpscan/trunk/app/Plugin.php

    r2429586 r2452411  
    5656    public $report;
    5757
     58    // Action fired when an issue is found
     59    public $WPSCAN_ISSUE_FOUND = 'wpscan_issue_found';
     60
    5861    /**
    5962     * Class constructor.
     
    7982        add_action( 'admin_bar_menu', array( $this, 'admin_bar' ), 65 );
    8083        add_action( $this->WPSCAN_SCHEDULE, array( $this, 'check_now' ) );
     84        add_action( 'in_admin_header', array( $this, 'deactivate_screen' ) );
     85
     86        // Check if wp cron is disabled
     87        if ( $this->is_wp_cron_disabled() ) {
     88            add_action( 'admin_notices', array( $this, 'wp_cron_alert' ) );
     89        }
    8190
    8291        if ( defined( 'WPSCAN_API_TOKEN' ) ) {
     
    129138     */
    130139    public function deactivate() {
     140        delete_option( $this->OPT_SCANNING_INTERVAL );
     141
     142        delete_option( $this->OPT_SCANNING_TIME );
     143
    131144        wp_clear_scheduled_hook( $this->WPSCAN_SCHEDULE );
     145    }
     146
     147    /**
     148     * Deactivate screen
     149     *
     150     * @since 1.14.0
     151     * @access public
     152     * @return void
     153     */
     154    public function deactivate_screen() {
     155        global $pagenow;
     156
     157        if ( 'plugins.php' === $pagenow ) {
     158            include_once plugin_dir_path( WPSCAN_PLUGIN_FILE ) . 'views/deactivate.php';
     159        }
     160    }
     161
     162    /**
     163     * Check if WP-Cron is disabled
     164     *
     165     * @since 1.14.0
     166     * @access public
     167     * @return bool
     168     */
     169    public function is_wp_cron_disabled() {
     170        return defined('DISABLE_WP_CRON') && DISABLE_WP_CRON;
     171    }
     172
     173    /**
     174     * Display cron disabled alert
     175     *
     176     * @since 1.14.0
     177     * @access public
     178     * @return void
     179     */
     180    public function wp_cron_alert() {
     181        echo "<div class='notice notice-error'><p>". __( 'WP-Cron has been disabled in the wp-config.php file using the <code>DISABLE_WP_CRON</code> constant. Automated scans and other features that rely on cron will not work.', 'wpscan' ) ."</p></div>";
    132182    }
    133183
     
    161211     */
    162212    public function admin_enqueue( $hook ) {
     213        global $pagenow;
    163214        $screen = get_current_screen();
    164215
     
    207258
    208259            wp_localize_script('wpscan', 'wpscan', $localized);
     260        }
     261
     262        if ( 'plugins.php' === $pagenow ) {
     263            wp_enqueue_style(
     264                'wpscan-deactivate',
     265                plugins_url( 'assets/css/deactivate.css', WPSCAN_PLUGIN_FILE ),
     266                array(),
     267                $this->wpscan_plugin_version()
     268            );
     269
     270            wp_enqueue_script(
     271                'wpscan-deactivate',
     272                plugins_url( 'assets/js/deactivate.js', WPSCAN_PLUGIN_FILE ),
     273                    array( 'jquery' ),
     274                    $this->wpscan_plugin_version()
     275            );
    209276        }
    210277    }
     
    387454
    388455        // Hook before the request.
    389         do_action( 'wpscan/api/get/before', $endpoint );
     456        //do_action( 'wpscan/api/get/before', $endpoint );
    390457
    391458        // Start the request.
     
    394461
    395462        // Hook after the request.
    396         do_action( 'wpscan/api/get/after', $endpoint, $response );
     463        //do_action( 'wpscan/api/get/after', $endpoint, $response );
    397464
    398465        if ( 200 === $code ) {
     
    479546        // Reset errors.
    480547        update_option( $this->OPT_ERRORS, array() );
     548        update_option( $this->classes['checks/system']->OPT_FATAL_ERRORS, array() );
    481549
    482550        // Plugins.
    483         $report['plugins'] = $this->verify_plugins( $ignored['plugins'] );
     551        $this->report['plugins'] = $this->verify_plugins( $ignored['plugins'] );
    484552
    485553        // Themes.
    486         $report['themes'] = $this->verify_themes( $ignored['themes'] );
     554        $this->report['themes'] = $this->verify_themes( $ignored['themes'] );
    487555
    488556        // WordPress.
    489557        if ( ! isset( $ignored['wordpress'] ) ) {
    490             $report['wordpress'] = $this->verify_wordpress();
     558            $this->report['wordpress'] = $this->verify_wordpress();
    491559        } else {
    492             $report['wordpress'] = array();
     560            $this->report['wordpress'] = array();
    493561        }
    494562
    495563        // Security checks.
    496         $report['security-checks'] = array();
     564        $this->report['security-checks'] = array();
    497565
    498566        foreach ( $this->classes['checks/system']->checks as $id => $data ) {
    499567            $data['instance']->perform();
    500             $report['security-checks'][ $id ]['vulnerabilities'] = array();
     568            $this->report['security-checks'][ $id ]['vulnerabilities'] = array();
    501569
    502570            if ( $data['instance']->vulnerabilities ) {
    503                 $report['security-checks'][ $id ]['vulnerabilities'] = $data['instance']->get_vulnerabilities();
     571                $this->report['security-checks'][ $id ]['vulnerabilities'] = $data['instance']->get_vulnerabilities();
     572
     573                $this->maybe_fire_issue_found_action('security-check', $id, $this->report['security-checks'][ $id ]);
    504574            }
    505575        }
    506576
    507577        // Caching.
    508         $report['cache'] = strtotime( current_time( 'mysql' ) );
     578        $this->report['cache'] = strtotime( current_time( 'mysql' ) );
    509579
    510580        // Saving.
    511         update_option( $this->OPT_REPORT, $report, true );
     581        update_option( $this->OPT_REPORT, $this->report, true );
     582
     583        // Updates account status (API calls etc).
     584        $this->classes['account']->update_account_status();
     585    }
     586
     587    /**
     588    * Fires the wpscan_issue_found action if needed
     589    *
     590    * @since 1.14.0
     591    *
     592    * @param string $type - The affected component type: plugin, theme, wordpress or security-check
     593    * @param string $slug - The affected component slug.
     594    *                       For wordpress, it will be the version (ie 5.5.3)
     595    *                       For security-checks, it will be the id of the check, ie xmlrpc-enabled
     596    * @param array $details - An array containing some keys, such as vulnerabilities
     597    * @param array additional_details - An array with the plugin details, such as Version etc
     598    **/
     599    public function maybe_fire_issue_found_action($type, $slug, $details, $additional_details = []) {
     600        if ( !count($details['vulnerabilities']) > 0) {
     601            return;
     602        }
     603
     604        do_action($this->WPSCAN_ISSUE_FOUND, $type, $slug, $details, $additional_details);
    512605    }
    513606
     
    546639                    $plugins[ $slug ]['closed'] = false;
    547640                }
     641
     642                $this->maybe_fire_issue_found_action('plugin', $slug, $plugins[ $slug ], $details );
    548643            } else {
    549644                if ( 404 === $result ) {
     
    596691                    $themes[ $slug ]['closed'] = false;
    597692                }
     693
     694                $this->maybe_fire_issue_found_action('theme', $slug, $themes[ $slug ], $details );
    598695            } else {
    599696                if ( 404 === $result ) {
     
    614711     */
    615712    public function verify_wordpress() {
    616         $wordperss = array();
     713        $wordpress = array();
    617714
    618715        $version = get_bloginfo( 'version' );
     
    620717
    621718        if ( is_object( $result ) ) {
    622             $wordperss[ $version ]['vulnerabilities'] = $this->get_vulnerabilities( $result, $version );
    623         }
    624 
    625         return $wordperss;
     719            $wordpress[ $version ]['vulnerabilities'] = $this->get_vulnerabilities( $result, $version );
     720
     721            $this->maybe_fire_issue_found_action('wordpress', $version, $wordpress[ $version ] );
     722        }
     723
     724        return $wordpress;
    626725    }
    627726
     
    812911     */
    813912    public function delete_doing_cron_transient() {
    814         $option = get_option( '_transient_wpscan_doing_cron' );
    815 
    816         if ( $option ) {
    817             delete_option( '_transient_wpscan_doing_cron' );
    818         }
     913        delete_transient( $this->WPSCAN_TRANSIENT_CRON );
    819914    }
    820915}
  • wpscan/trunk/app/Report.php

    r2429586 r2452411  
    1616{
    1717    // Page slug.
    18     private $page;
     18    public $page;
    1919
    2020    /**
  • wpscan/trunk/app/Settings.php

    r2429586 r2452411  
    2929        add_action( 'admin_init', array( $this, 'admin_init' ) );
    3030        add_action( 'admin_notices', array( $this, 'got_api_token' ) );
    31 
    3231        add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue' ) );
    3332
    34         add_action( 'add_option_' . $this->parent->OPT_SCANNING_INTERVAL, array( $this, 'schedule_event' ), 10, 2 );
    35         add_action( 'update_option_' . $this->parent->OPT_SCANNING_INTERVAL, array( $this, 'schedule_event' ), 10, 3 );
    36         add_action( 'update_option_' . $this->parent->OPT_SCANNING_TIME, array( $this, 'schedule_event' ), 10, 3 );
    37 
    38         add_action( 'update_option_' . $this->parent->OPT_IGNORE_ITEMS, array( $this, 'update_ignored_items' ), 10, 3 );
     33        if ( ! $this->parent->is_wp_cron_disabled() ) {
     34            add_action( 'add_option_' . $this->parent->OPT_SCANNING_INTERVAL, array( $this, 'schedule_event' ), 10, 2 );
     35            add_action( 'update_option_' . $this->parent->OPT_SCANNING_INTERVAL, array( $this, 'schedule_event' ), 10, 2 );
     36            add_action( 'update_option_' . $this->parent->OPT_SCANNING_TIME, array( $this, 'schedule_event' ), 10, 2 );
     37        }
     38
     39        add_action( 'update_option_' . $this->parent->OPT_IGNORE_ITEMS, array( $this, 'update_ignored_items' ), 10, 2 );
    3940    }
    4041
     
    6263                'wpscan-settings',
    6364                plugins_url( 'assets/css/settings.css', WPSCAN_PLUGIN_FILE ),
    64                 array(),
    65                 $this->parent->wpscan_plugin_version()
     65                    array(),
     66                    $this->parent->wpscan_plugin_version()
    6667            );
    6768        }
     
    7677     */
    7778    public function admin_init() {
    78         register_setting( $this->page, $this->parent->OPT_API_TOKEN, array( $this, 'sanitize_api_token' ) );
    79         register_setting( $this->page, $this->parent->OPT_SCANNING_INTERVAL, 'sanitize_text_field' );
    80         register_setting( $this->page, $this->parent->OPT_SCANNING_TIME, 'sanitize_text_field' );
     79        // No need to sanitise the API token from the Settings form if we are using the token from the
     80        // WPSCAN_API_TOKEN constant. register_setting() is run before WPSCAN_API_TOKEN is placed in the database,
     81        // causing a NULL API token to be passed to some functions if called when using a WPSCAN_API_TOKEN constant.
     82        if ( ! defined( 'WPSCAN_API_TOKEN' ) ) {
     83            register_setting( $this->page, $this->parent->OPT_API_TOKEN, array( 'sanitize_callback' => array( $this, 'sanitize_api_token' ) ) );
     84        }
     85
    8186        register_setting( $this->page, $this->parent->OPT_IGNORE_ITEMS );
     87
     88        if ( ! $this->parent->is_wp_cron_disabled() ) {
     89            register_setting( $this->page, $this->parent->OPT_SCANNING_INTERVAL, 'sanitize_text_field' );
     90            register_setting( $this->page, $this->parent->OPT_SCANNING_TIME, 'sanitize_text_field' );
     91        }
    8292
    8393        $section = $this->page . '_section';
     
    98108        );
    99109
    100         add_settings_field(
    101             $this->parent->OPT_SCANNING_INTERVAL,
    102             __( 'Automated Scanning', 'wpscan' ),
    103             array( $this, 'field_scanning_interval' ),
    104             $this->page,
    105             $section
    106         );
    107 
    108         add_settings_field(
    109             $this->parent->OPT_SCANNING_TIME,
    110             __( 'Scanning Time', 'wpscan' ),
    111             array( $this, 'field_scanning_time' ),
    112             $this->page,
    113             $section
    114         );
     110        if ( ! $this->parent->is_wp_cron_disabled() ) {
     111
     112            add_settings_field(
     113                $this->parent->OPT_SCANNING_INTERVAL,
     114                __( 'Automated Scanning', 'wpscan' ),
     115                array( $this, 'field_scanning_interval' ),
     116                $this->page,
     117                $section
     118            );
     119
     120            add_settings_field(
     121                $this->parent->OPT_SCANNING_TIME,
     122                __( 'Scanning Time', 'wpscan' ),
     123                array( $this, 'field_scanning_time' ),
     124                $this->page,
     125                $section
     126            );
     127
     128        }
    115129
    116130        add_settings_field(
     
    210224            echo '</form>';
    211225        echo '</div>';
    212   }
     226    }
    213227
    214228    /**
     
    302316    public function field_scanning_time() {
    303317        $opt      = $this->parent->OPT_SCANNING_TIME;
    304         $value    = esc_attr( get_option( $opt, '12:00' ) );
     318        $value    = esc_attr( get_option( $opt, date('H:i') ) );
    305319        $disabled = $this->parent->is_interval_scanning_disabled() ? "disabled='true'" : null;
    306320
     
    367381            : __( 'Plugins', 'wpscan' );
    368382
    369 
    370383        echo "<div class='wpscan-ignore-items-section'>";
    371384
     
    397410    public function sanitize_api_token( $value ) {
    398411        $value  = trim( $value );
    399         $result = $this->parent->api_get( '/status', $value );
     412
     413        // update_account_status() calls the /status API endpoint, verifying the validity of the Token passed via $value and updates the account status if needed.
     414        if ( empty( $value ) ) {
     415            delete_option( $this->parent->OPT_ACCOUNT_STATUS );
     416        } else {
     417            $this->parent->classes['account']->update_account_status( $value );
     418        }
    400419
    401420        $errors = get_option( $this->parent->OPT_ERRORS );
     
    432451        if ( ! empty( $api_token ) && $old_value !== $value ) {
    433452            $interval = esc_attr( get_option( $this->parent->OPT_SCANNING_INTERVAL, 'daily' ) );
    434             $time     = esc_attr( get_option( $this->parent->OPT_SCANNING_TIME, '12:00 +1day' ) );
     453            $time     = esc_attr( get_option( $this->parent->OPT_SCANNING_TIME, date('H:i') . ' +1day' ) );
    435454
    436455            wp_clear_scheduled_hook( $this->parent->WPSCAN_SCHEDULE );
  • wpscan/trunk/app/Summary.php

    r2429586 r2452411  
    6767        ?>
    6868
     69        <?php
     70            if ( ! empty( $errors ) ) {
     71                foreach ( $errors as $err ) {
     72                    // $err should not contain user input. If you like to add an esc_html() here, be sure to update the error text that use HTML
     73                    echo '<p class="wpscan-summary-res is-red"><span class="dashicons dashicons-megaphone"></span> <strong>' . $err . '</strong></p>';
     74                }
     75            } elseif ( empty( $this->parent->get_report() ) ) { // No scan run yet.
     76                echo '<p class="wpscan-summary-res is-red"><span class="dashicons dashicons-megaphone"></span> <strong>' . __( 'No scan run yet!', 'wpscan' ) . '</strong></p>';
     77            } elseif ( empty( $errors ) && 0 === $total ) {
     78                echo '<p class="wpscan-summary-res is-green"><span class="dashicons dashicons-awards"></span> <strong>' . __( 'No known vulnerabilities found', 'wpscan' ) . '</strong></p>';
     79            } elseif( ! get_option( $this->parent->OPT_API_TOKEN ) ) {
     80                echo '<p class="wpscan-summary-res is-red"><span class="dashicons dashicons-megaphone"></span> <strong>' . __( 'You need to add a WPScan API Token to the settings page', 'wpscan' ) . '</strong></p>';
     81            } else {
     82                echo '<p class="wpscan-summary-res is-red"><span class="dashicons dashicons-megaphone"></span> <strong>' . __( 'Some vulnerabilities were found', 'wpscan' ) . '</strong></p>';
     83            }
     84        ?>
     85
    6986        <p>
    7087            <?php _e( 'The last full scan was run on: ', 'wpscan' ) ?>
     
    84101        </p>
    85102
    86             <?php
    87                 // Only show next scan time if there's a scheduled cron job.
    88                 if ( wp_next_scheduled( $this->parent->WPSCAN_SCHEDULE ) ) {
    89             ?>
     103            <?php if ( ! $this->parent->is_wp_cron_disabled() && wp_next_scheduled( $this->parent->WPSCAN_SCHEDULE ) ) { ?>
    90104                <p>
    91105                    <?php _e( 'The next scan will automatically be run on ', 'wpscan' ) ?>
     
    96110        <?php } ?>
    97111
    98         <?php
    99             if ( ! empty( $errors ) ) {
    100                 foreach ( $errors as $err ) {
    101                     // $err should not contain user input. If you like to add an esc_html() here, be sure to update the error text that use HTML
    102                     echo '<p class="wpscan-summary-res is-red"><span class="dashicons dashicons-megaphone"></span> <strong>' . $err . '</strong></p>';
     112        <p class="description">
     113            <?php
     114                if ( get_option( $this->parent->OPT_API_TOKEN ) ) {
     115                    _e( 'Click the Run All button to run a full vulnerability scan against your WordPress website.', 'wpscan' );
     116                } else {
     117                    _e( 'Add your API token to the settings page to be able to run a full scan.', 'wpscan' );
    103118                }
    104             } elseif ( empty( $this->parent->get_report() ) ) { // No scan run yet.
    105                 echo '<p class="wpscan-summary-res is-red"><span class="dashicons dashicons-megaphone"></span> <strong>' . __( 'No scan run yet!', 'wpscan' ) . '</strong></p>';
    106             } elseif ( empty( $errors ) && 0 === $total ) {
    107                 echo '<p class="wpscan-summary-res is-green"><span class="dashicons dashicons-awards"></span> <strong>' . __( 'No known vulnerabilities found', 'wpscan' ) . '</strong></p>';
    108             } elseif( ! get_option($this->parent->OPT_API_TOKEN) ) {
    109                 echo '<p class="wpscan-summary-res is-red"><span class="dashicons dashicons-megaphone"></span> <strong>' . __( 'You need to add a WPScan API Token to the settings page', 'wpscan' ) . '</strong></p>';
    110             } else {
    111                 echo '<p class="wpscan-summary-res is-red"><span class="dashicons dashicons-megaphone"></span> <strong>' . __( 'Some vulnerabilities were found', 'wpscan' ) . '</strong></p>';
    112             }
    113         ?>
    114 
    115         <p class="description">
    116             <?php _e( 'Click the Run All button to run a full vulnerability scan against your WordPress website.', 'wpscan' ) ?>
     119            ?>
    117120        </p>
    118121
  • wpscan/trunk/assets/css/style.css

    r2417112 r2452411  
    1010  margin-bottom: 5px;
    1111  margin-right: 12px;
     12  white-space: normal !important;
     13}
     14
     15.column-name {
     16  word-break: break-word;
     17  width: 250px;
    1218}
    1319
  • wpscan/trunk/assets/js/scripts.js

    r2424629 r2452411  
    3232      success: function( ) {
    3333        check_cron();
     34      },
     35      error: function () {
     36        location.reload();
    3437      }
    3538    } );
     
    5659        },
    5760        error: function ( ) {
    58           check_cron();
     61          location.reload();
    5962        }
    6063      } );
  • wpscan/trunk/readme.txt

    r2433081 r2452411  
    33Tags: wpscan, wpvulndb, security, vulnerability, hack, scan, exploit, secure, alerts
    44Requires at least: 3.4
    5 Tested up to: 5.5.3
    6 Stable tag: 1.13.2
     5Tested up to: 5.6
     6Stable tag: 1.14
    77Requires PHP: 5.5
    88License: GPLv3
     
    48484. Save the API token to the WPScan settings page or within the wp-config.php file
    4949
    50 == FAQ ==
     50== Frequently Asked Questions ==
    5151
    52 * How many API calls are made?
     52= How many API calls are made? =
    5353
    5454  There is one API call made for the WordPress version, one call for each installed plugin and one for each theme. By default there is one scan per day. The number of daily scans can be configured when configuring notifications.
    5555
    56 * How can I configure the API token in the wp-config.php file?
     56= How can I configure the API token in the wp-config.php file? =
    5757
    5858  To configure your API token in the wp-config.php file, use the following PHP code: `define( 'WPSCAN_API_TOKEN', '$your_api_token' );`
    5959
    60 * How do I disable vulnerability scanning altogether?
     60= How do I disable vulnerability scanning altogether? =
    6161
    6262  You can set the following PHP constant in the wp-config.php file to disable scanning; `define( 'WPSCAN_DISABLE_SCANNING_INTERVAL', true );`.
    6363
    64 * Why is the "Summary" section and the "Run All" button not showing?
     64= Why is the "Summary" section and the "Run All" button not showing? =
    6565
    6666  The cron job did not run, which can be due to:
     
    7878
    7979== Changelog ==
     80
     81= 1.14 =
     82
     83* Uses the status endpoint to get account data
     84* Fixes the account status not being updated unless a scan is performed when the API token is updated/set
     85* Adds vulnerability found hook
     86* New security check: Check for weak user passwords
     87* New security check: HTTPS
     88* Clear plan info if API Token set to null
     89* Fixes automated scanning when plugin deactivated and reactivated
     90* Fixes cron job not being created when using the WPSCAN_API_TOKEN constant
     91* Change default scanning time to the current time
     92* Many other small improvements
    8093
    8194= 1.13.2 =
  • wpscan/trunk/security-checks/xmlrpc-enabled/check.php

    r2433081 r2452411  
    7676        } else {
    7777            if ( preg_match( '/<string>Incorrect username or password.<\/string>/', $authenticated_response['body'] ) ) {
    78                 $this->add_vulnerability( __( 'The XML-RPC interface is enabled. This significantly increases your site\'s attack surface.', 'wpscan' ), 'medium', sanitize_title( $url ) );
     78                $this->add_vulnerability( __( 'The XML-RPC interface is enabled. This significantly increases your site\'s attack surface', 'wpscan' ), 'medium', sanitize_title( $url ) );
    7979                return;
    8080            } else {
     
    8484
    8585                if ( preg_match( '/<string>Hello!<\/string>/', $unauthenticated_response['body'] ) ) {
    86                     $this->add_vulnerability( __( 'The XML-RPC interface is partly disabled, but still allows unauthenticated requests.', 'wpscan' ), 'low', sanitize_title( $url ) );
     86                    $this->add_vulnerability( __( 'The XML-RPC interface is partly disabled, but still allows unauthenticated requests', 'wpscan' ), 'low', sanitize_title( $url ) );
    8787                }
    8888            }
  • wpscan/trunk/views/report.php

    r2429586 r2452411  
    88
    99<div class="wrap">
    10   <?php echo file_get_contents($this->parent->plugin_dir. 'assets/svg/logo.svg'); ?>
     10  <h1>
     11    <?php echo file_get_contents($this->parent->plugin_dir. 'assets/svg/logo.svg'); ?>
     12  </h1>
    1113 
    1214  <hr class="wp-header-end">
     
    4143              <tr>
    4244                <td scope="col" class="manage-column check-column">&nbsp;</td>
    43                 <th scope="col" class="manage-column column-name column-primary" width="250"><?php _e( 'Name', 'wpscan' ) ?></th>
     45                <th scope="col" class="manage-column column-name column-primary"><?php _e( 'Name', 'wpscan' ) ?></th>
    4446                <th scope="col" class="manage-column column-description"><?php _e( 'Vulnerabilities', 'wpscan' ) ?></th>
    4547              </tr>
     
    7678                <tr>
    7779                  <td scope="col" class="manage-column check-column">&nbsp;</td>
    78                   <th scope="col" class="manage-column column-name column-primary" width="250"><?php _e( 'Name', 'wpscan' ) ?></th>
     80                  <th scope="col" class="manage-column column-name column-primary"><?php _e( 'Name', 'wpscan' ) ?></th>
    7981                  <th scope="col" class="manage-column column-description"><?php _e( 'Vulnerabilities', 'wpscan' ) ?></th>
    8082                </tr>
     
    8385                <?php
    8486                  foreach ( get_plugins() as $name => $details ) {
    85                     $slug = $this->parent->get_plugin_slug( $name, $details );
     87                    $slug      = $this->parent->get_plugin_slug( $name, $details );
    8688                    $is_closed = $this->is_item_closed('plugins', $slug);
    8789                ?>
     
    124126                <tr>
    125127                  <td scope="col" class="manage-column check-column">&nbsp;</td>
    126                   <th scope="col" class="manage-column column-name column-primary" width="250"><?php _e( 'Name', 'wpscan' ) ?></th>
     128                  <th scope="col" class="manage-column column-name column-primary"><?php _e( 'Name', 'wpscan' ) ?></th>
    127129                  <th scope="col" class="manage-column column-description"><?php _e( 'Vulnerabilities', 'wpscan' ) ?></th>
    128130                </tr>
     
    168170                    <tr>
    169171                        <td scope="col" class="manage-column check-column"></td>
    170                         <th scope="col" class="manage-column column-name column-primary" width="250"><?php _e('Name', 'wpscan') ?></th>
     172                        <th scope="col" class="manage-column column-name column-primary"><?php _e('Name', 'wpscan') ?></th>
    171173                        <th scope="col" class="manage-column column-description"><?php _e('Result', 'wpscan') ?></th>
    172174                        <th scope="col" class="manage-column column-description"><?php _e('Actions', 'wpscan') ?></th>
  • wpscan/trunk/wpscan.php

    r2433081 r2452411  
    44 * Plugin URI:    http://wordpress.org/plugins/wpscan/
    55 * Description:   WPScan WordPress Security Scanner. Scans your system for security vulnerabilities listed in the WPScan Vulnerability Database.
    6  * Version:       1.13.2
     6 * Version:       1.14
    77 * Author:        WPScan Team
    88 * Author URI:    https://wpscan.com/
Note: See TracChangeset for help on using the changeset viewer.