gmdate( get_option( 'date_format', 'F j, Y' ), strtotime( '-1 day', $date_from ) ), 'before' => gmdate( get_option( 'date_format', 'F j, Y' ), strtotime( '+1 day', $date_from ) ), ); if ( $date_to ) { $date_query_attr['before'] = gmdate( get_option( 'date_format', 'F j, Y' ), strtotime( '+1 day', $date_to ) ); } $query->set( 'date_query', $date_query_attr ); } } return $query; } /** * Handle secure actions. * * @since 2.6.8 */ public function admin_init() { global $wpdb; if ( isset( $_REQUEST['um_secure_expire_all_sessions'] ) && ! wp_doing_ajax() ) { if ( ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'um-secure-expire-session-nonce' ) || ! current_user_can( 'manage_options' ) ) { // This nonce is not valid or current logged-in user has no administrative rights. wp_die( esc_html__( 'Security check', 'ultimate-member' ) ); } /** * Destroy all user sessions except the current logged-in user. */ $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->usermeta} WHERE meta_key='session_tokens' AND user_id != %d", get_current_user_id() ) ); if ( UM()->options()->get( 'display_login_form_notice' ) ) { global $wpdb; $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->usermeta} WHERE user_id != %d AND ( meta_key = 'um_secure_has_reset_password' OR meta_key = 'um_secure_has_reset_password__timestamp' )", get_current_user_id() ) ); } wp_safe_redirect( add_query_arg( 'update', 'um_secure_expire_sessions', wp_get_referer() ) ); exit; } if ( isset( $_REQUEST['um_secure_restore_account'], $_REQUEST['user_id'] ) && ! wp_doing_ajax() ) { $user_id = absint( $_REQUEST['user_id'] ); if ( ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'um-security-restore-account-nonce-' . $user_id ) || ! current_user_can( 'manage_options' ) ) { // This nonce is not valid or current logged-in user has no administrative rights. wp_die( esc_html__( 'Security check', 'ultimate-member' ) ); } $user = get_userdata( $user_id ); if ( ! $user ) { wp_die( esc_html__( 'Invalid user.', 'ultimate-member' ) ); } um_fetch_user( $user_id ); $metadata = get_user_meta( $user_id, 'um_user_blocked__metadata', true ); $user->update_user_level_from_caps(); // Restore Roles. if ( isset( $metadata['roles'] ) ) { foreach ( $metadata['roles'] as $role ) { $user->add_role( $role ); } } // Restore Account Status. if ( isset( $metadata['account_status'] ) ) { // Force update of the user status without email notifications. UM()->common()->users()->set_status( $user_id, $metadata['account_status'] ); } // Delete blocked meta. delete_user_meta( $user_id, 'um_user_blocked__metadata' ); delete_user_meta( $user_id, 'um_user_blocked' ); delete_user_meta( $user_id, 'um_user_blocked__timestamp' ); // Don't need to reset a password. if ( UM()->options()->get( 'display_login_form_notice' ) ) { update_user_meta( $user_id, 'um_secure_has_reset_password', true ); update_user_meta( $user_id, 'um_secure_has_reset_password__timestamp', current_time( 'mysql', true ) ); } // Clear Cache. UM()->user()->remove_cache( $user_id ); um_reset_user(); wp_safe_redirect( add_query_arg( 'update', 'um_secure_restore', wp_get_referer() ) ); exit; } } /** * Register Secure Settings * * @since 2.6.8 * * @param array $settings * @return array */ public function add_settings( $settings ) { $nonce = wp_create_nonce( 'um-secure-expire-session-nonce' ); $banned_capabilities = array(); $banned_admin_capabilities = UM()->common()->secure()->get_banned_capabilities_list(); foreach ( $banned_admin_capabilities as $cap ) { $banned_capabilities[ $cap ] = $cap; } $disabled_capabilities = UM()->options()->get_default( 'banned_capabilities' ); $disabled_capabilities_text = '' . implode( ', ', $disabled_capabilities ) . ''; $scanner_content = ''; $scanner_content .= ''; $scanner_content .= esc_html__( 'Last scan:', 'ultimate-member' ) . ' '; $scan_status = get_option( 'um_secure_scan_status' ); $last_scanned_time = get_option( 'um_secure_last_time_scanned' ); if ( ! empty( $last_scanned_time ) ) { $scanner_content .= human_time_diff( strtotime( $last_scanned_time ) ) . ' ' . esc_html__( 'ago', 'ultimate-member' ); if ( 'started' === $scan_status ) { $scanner_content .= ' - ' . esc_html__( 'Not Completed.', 'ultimate-member' ); } } else { $scanner_content .= esc_html__( 'Not Scanned yet.', 'ultimate-member' ); } $scanner_content .= ''; $secure_fields = array( array( 'id' => 'banned_capabilities', 'type' => 'multi_checkbox', 'multi' => true, 'assoc' => true, 'checkbox_key' => true, 'columns' => 2, 'options_disabled' => $disabled_capabilities, 'options' => $banned_capabilities, 'label' => __( 'Banned Administrative Capabilities', 'ultimate-member' ), // translators: %s are disabled default capabilities that are enabled by default. 'description' => sprintf( __( 'All the above are default Administrator & Super Admin capabilities. When someone tries to inject capabilities to the Account, Profile & Register forms submission, it will be flagged with this option. The %s capabilities are locked to ensure no users will be created with these capabilities.', 'ultimate-member' ), $disabled_capabilities_text ), ), array( 'id' => 'secure_scan_affected_users', 'type' => 'info_text', 'label' => __( 'Scanner', 'ultimate-member' ), 'value' => $scanner_content, 'description' => __( 'Scan your site to check for vulnerabilities prior to Ultimate Member version 2.6.7 and get recommendations to secure your site.', 'ultimate-member' ), ), array( 'id' => 'lock_register_forms', 'type' => 'checkbox', 'label' => __( 'Lock All Register Forms', 'ultimate-member' ), 'checkbox_label' => __( 'Lock Forms', 'ultimate-member' ), 'description' => __( 'This prevents all users from registering with Ultimate Member on your site.', 'ultimate-member' ), ), array( 'id' => 'display_login_form_notice', 'type' => 'checkbox', 'label' => __( 'Display Login form notice to reset passwords', 'ultimate-member' ), 'checkbox_label' => __( 'Enable Login form notice', 'ultimate-member' ), 'description' => __( 'Enforces users to reset their passwords (one-time) and prevent from entering old password.', 'ultimate-member' ), ), ); global $wpdb; $count_users = $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->users}" ); $count_users_exclude_me = $count_users - 1; if ( $count_users_exclude_me > 0 ) { $secure_fields[] = array( 'id' => 'force_reset_passwords', 'type' => 'info_text', 'label' => __( 'Expire All Users Sessions', 'ultimate-member' ), // translators: %d is the users count. 'value' => '' . esc_html( sprintf( __( 'Logout Users (%d)', 'ultimate-member' ), $count_users_exclude_me ) ) . '', 'description' => __( 'This will log out all users on your site and forces them to reset passwords
when "Display Login form notice to reset passwords" is enabled/checked.', 'ultimate-member' ), ); } $secure_fields = array_merge( $secure_fields, array( array( 'id' => 'secure_ban_admins_accounts', 'type' => 'checkbox', 'label' => __( 'Administrative capabilities ban', 'ultimate-member' ), 'checkbox_label' => __( 'Enable ban for administrative capabilities', 'ultimate-member' ), 'description' => __( ' When someone tries to inject capabilities to the Account, Profile & Register forms submission, it will be banned.', 'ultimate-member' ), ), array( 'id' => 'secure_notify_admins_banned_accounts', 'type' => 'checkbox', 'label' => __( 'Notify Administrators', 'ultimate-member' ), 'checkbox_label' => __( 'Enable notification', 'ultimate-member' ), 'description' => __( 'When enabled, All administrators will be notified when someone has suspicious activities in the Account, Profile & Register forms.', 'ultimate-member' ), 'conditional' => array( 'secure_ban_admins_accounts', '=', 1 ), ), array( 'id' => 'secure_notify_admins_banned_accounts__interval', 'type' => 'select', 'options' => array( 'instant' => __( 'Send Immediately', 'ultimate-member' ), 'hourly' => __( 'Hourly', 'ultimate-member' ), 'daily' => __( 'Daily', 'ultimate-member' ), ), 'label' => __( 'Notification Schedule', 'ultimate-member' ), 'conditional' => array( 'secure_notify_admins_banned_accounts', '=', 1 ), ), array( 'id' => 'secure_allowed_redirect_hosts', 'type' => 'textarea', 'label' => __( 'Allowed hosts for safe redirect (one host per line)', 'ultimate-member' ), 'description' => __( 'Extend allowed hosts for frontend pages redirects.', 'ultimate-member' ), ), ) ); $settings['advanced']['sections'] = UM()->array_insert_before( $settings['advanced']['sections'], 'developers', array( 'security' => array( 'title' => __( 'Security', 'ultimate-member' ), 'description' => __( 'This feature scans for suspicious registered accounts, bans the usage of administrative capabilities to site subscribers/members, allows the website administrators to force all users to reset their passwords, preventing users from logging-in using their old passwords that may have been exposed.', 'ultimate-member' ), 'fields' => $secure_fields, ), ) ); return $settings; } /** * Append blocked status to the `account_status` column rows. * * @param string $val Default column row value. * @param string $column_name Current column name. * @param int $user_id User ID in loop. * * @since 2.6.8 * * @return string */ public function add_restore_account( $val, $column_name, $user_id ) { if ( 'account_status' === $column_name ) { um_fetch_user( $user_id ); $is_blocked = um_user( 'um_user_blocked' ); $account_status = UM()->common()->users()->get_status( $user_id ); if ( ! empty( $is_blocked ) && in_array( $account_status, array( 'rejected', 'inactive' ), true ) ) { $datetime = um_user( 'um_user_blocked__timestamp' ); $val .= '
' . esc_html__( 'Blocked Due to Suspicious Activity', 'ultimate-member' ) . '
'; $nonce = wp_create_nonce( 'um-security-restore-account-nonce-' . $user_id ); $restore_account_url = admin_url( 'users.php?user_id=' . $user_id . '&um_secure_restore_account=1&_wpnonce=' . $nonce ); $action = ' · ' . esc_html__( 'Restore Account', 'ultimate-member' ) . ''; if ( ! empty( $datetime ) ) { $val .= '
' . human_time_diff( strtotime( $datetime ) ) . ' ' . __( 'ago', 'ultimate-member' ) . '' . $action . '
'; } } um_reset_user(); } return $val; } /** * */ public function check_secure_changes() { if ( isset( $_POST['um_options']['display_login_form_notice'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification $current_option_value = UM()->options()->get( 'display_login_form_notice' ); if ( empty( $current_option_value ) ) { return; } if ( empty( $_POST['um_options']['display_login_form_notice'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification $this->need_flush_meta = true; } } } /** * */ public function on_settings_save() { if ( isset( $_POST['um_options']['display_login_form_notice'] ) && ! empty( $this->need_flush_meta ) ) { //phpcs:ignore WordPress.Security.NonceVerification global $wpdb; $wpdb->query( "DELETE FROM {$wpdb->usermeta} WHERE meta_key = 'um_secure_has_reset_password' OR meta_key = 'um_secure_has_reset_password__timestamp'" ); } if ( isset( $_POST['um_options']['secure_notify_admins_banned_accounts'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification if ( ! empty( $_POST['um_options']['secure_notify_admins_banned_accounts'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification UM()->options()->update( 'suspicious-activity_on', 1 ); } else { UM()->options()->update( 'suspicious-activity_on', 0 ); } } } } }