• Trouble with WordPress.Security.NonceVerification.Missing Processing form data without nonce verification. and WordPress.DB.DirectDatabaseQuery.DirectQuery Use of a direct database call is discouraged.

    Hello I hope I am not wrong here I just programmed with chatgpt and other ai’s this plugin below attached and in the screensgot is the error I keep getting regardless what the ai’s are trying they can never solve the issue any help would be appreciated!

    <?php
    /*
    Plugin Name: Unknown
    Description: Unknown
    Version: Unknown
    Author: Unknown Source
    License: GPLv2 or later
    Text Domain: secure-user-lookup
    */

    // Prevent direct file access
    if (!defined('ABSPATH')) {
    exit;
    }

    class SecureUserLookupAPI {
    private $api_key;
    private $api_secret;
    private $allowed_ips;
    private $allowed_domains;
    private $blocked_table;
    private $max_failed_attempts;
    private $lockout_time;

    public function __construct() {
    global $wpdb;
    $this->blocked_table = $wpdb->prefix . 'user_lookup_blocked';

    // Initialize plugin
    $this->init();

    // Load settings after init
    $this->load_settings();
    }

    private function init() {
    // Register activation hook
    register_activation_hook(__FILE__, array($this, 'plugin_activate'));

    // Add menu item
    add_action('admin_menu', array($this, 'add_admin_menu'));

    // Register API endpoint
    add_action('rest_api_init', array($this, 'register_api_endpoint'));

    // Enforce SSL if enabled
    add_action('template_redirect', array($this, 'force_ssl_redirect'));
    }

    public function plugin_activate() {
    // Create blocked table
    $this->create_blocked_table();

    // Initialize default settings if they don't exist
    if (!get_option('user_lookup_api_key')) {
    $this->generate_api_key();
    }

    if (!get_option('user_lookup_api_secret')) {
    $this->generate_api_secret();
    }

    if (!get_option('user_lookup_allowed_ips')) {
    update_option('user_lookup_allowed_ips', array());
    }

    if (!get_option('user_lookup_allowed_domains')) {
    update_option('user_lookup_allowed_domains', array());
    }

    if (!get_option('user_lookup_force_ssl')) {
    update_option('user_lookup_force_ssl', true);
    }

    if (!get_option('user_lookup_max_failed_attempts')) {
    update_option('user_lookup_max_failed_attempts', 5);
    }

    if (!get_option('user_lookup_lockout_time')) {
    update_option('user_lookup_lockout_time', 300); // 5 minutes
    }

    // Create empty index files
    $this->create_empty_index_files();
    }

    private function create_empty_index_files() {
    $plugin_dir = plugin_dir_path(__FILE__);
    $directories = array(
    $plugin_dir,
    $plugin_dir . 'templates/'
    );

    // Use WP_Filesystem for file operations
    global $wp_filesystem;
    if (!function_exists('WP_Filesystem')) {
    require_once(ABSPATH . 'wp-admin/includes/file.php');
    }
    WP_Filesystem();

    foreach ($directories as $dir) {
    if (!$wp_filesystem->exists($dir)) {
    $wp_filesystem->mkdir($dir, 0755, true);
    }
    $wp_filesystem->put_contents($dir . 'index.php', '<?php // Silence is golden.');
    }
    }

    public function create_blocked_table() {
    global $wpdb;

    $charset_collate = $wpdb->get_charset_collate();

    $sql = "CREATE TABLE IF NOT EXISTS $this->blocked_table (
    id bigint(20) NOT NULL AUTO_INCREMENT,
    ip_address varchar(45) NOT NULL,
    blocked_until datetime NOT NULL,
    permanent_block tinyint(1) DEFAULT 0,
    PRIMARY KEY (id)
    ) $charset_collate;";

    require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    dbDelta($sql);
    }

    private function load_settings() {
    $this->api_key = get_option('user_lookup_api_key', '');
    $this->api_secret = get_option('user_lookup_api_secret', '');
    $this->allowed_ips = get_option('user_lookup_allowed_ips', array());
    $this->allowed_domains = get_option('user_lookup_allowed_domains', array());
    $this->max_failed_attempts = get_option('user_lookup_max_failed_attempts', 5);
    $this->lockout_time = get_option('user_lookup_lockout_time', 300);

    // Generate API key and secret if they don't exist
    if (empty($this->api_key)) {
    $this->api_key = $this->generate_api_key();
    }
    if (empty($this->api_secret)) {
    $this->api_secret = $this->generate_api_secret();
    }
    }

    private function generate_api_key() {
    $api_key = bin2hex(random_bytes(32));
    update_option('user_lookup_api_key', $api_key);
    return $api_key;
    }

    private function generate_api_secret() {
    $api_secret = bin2hex(random_bytes(32));
    update_option('user_lookup_api_secret', $api_secret);
    return $api_secret;
    }

    public function add_admin_menu() {
    add_menu_page(
    'User Lookup API',
    'User Lookup API',
    'manage_options',
    'user-lookup-settings',
    array($this, 'render_admin_page'),
    'dashicons-search'
    );
    }

    public function render_admin_page() {
    // Verify admin access
    if (!current_user_can('manage_options')) {
    wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'secure-user-lookup'));
    }

    // Add nonce field to the form
    wp_nonce_field('user_lookup_settings_nonce_action', 'user_lookup_settings_nonce_field');

    // Handle form submission
    if (isset($_POST['submit']) && check_admin_referer('user_lookup_settings_nonce_action', 'user_lookup_settings_nonce_field')) {
    $this->save_settings();
    }

    // Regenerate API secret
    if (isset($_POST['regenerate_api_secret']) && check_admin_referer('user_lookup_settings_nonce_action', 'user_lookup_settings_nonce_field')) {
    $this->api_secret = $this->generate_api_secret();
    update_option('user_lookup_api_secret', $this->api_secret);
    }

    // Regenerate API key
    if (isset($_POST['regenerate_api_key']) && check_admin_referer('user_lookup_settings_nonce_action', 'user_lookup_settings_nonce_field')) {
    $this->api_key = $this->generate_api_key();
    update_option('user_lookup_api_key', $this->api_key);
    }

    // Handle unblock and permanent block actions
    if (isset($_POST['unblock_ip']) && check_admin_referer('user_lookup_settings_nonce_action', 'user_lookup_settings_nonce_field')) {
    $this->unblock_ip(sanitize_text_field(wp_unslash($_POST['unblock_ip'])));
    }
    if (isset($_POST['permanent_block_ip']) && check_admin_referer('user_lookup_settings_nonce_action', 'user_lookup_settings_nonce_field')) {
    $this->permanent_block_ip(sanitize_text_field(wp_unslash($_POST['permanent_block_ip'])));
    }

    // Retrieve blocked IPs with caching
    $blocked_ips = wp_cache_get('blocked_ips', 'secure_user_lookup');
    if (false === $blocked_ips) {
    global $wpdb;
    $blocked_ips = $wpdb->get_results(
    $wpdb->prepare("SELECT * FROM " . esc_sql($this->blocked_table))
    );
    wp_cache_set('blocked_ips', $blocked_ips, 'secure_user_lookup', 3600); // Cache for 1 hour
    }

    // Include admin template
    $template_path = plugin_dir_path(__FILE__) . 'templates/admin-page.php';
    if (file_exists($template_path)) {
    include($template_path);
    } else {
    echo esc_html__('Error: Template file not found', 'secure-user-lookup');
    }
    }

    private function save_settings() {
    if (isset($_POST['allowed_ips'])) {
    $ips = array_filter(array_map('trim', explode("\n", sanitize_textarea_field(wp_unslash($_POST['allowed_ips'])))));
    update_option('user_lookup_allowed_ips', $ips);
    $this->allowed_ips = $ips;
    }

    if (isset($_POST['allowed_domains'])) {
    $domains = array_filter(array_map('trim', explode("\n", sanitize_textarea_field(wp_unslash($_POST['allowed_domains'])))));
    update_option('user_lookup_allowed_domains', $domains);
    $this->allowed_domains = $domains;
    }

    if (isset($_POST['max_failed_attempts'])) {
    $max_failed_attempts = intval(sanitize_text_field(wp_unslash($_POST['max_failed_attempts'])));
    update_option('user_lookup_max_failed_attempts', $max_failed_attempts);
    $this->max_failed_attempts = $max_failed_attempts;
    }

    if (isset($_POST['lockout_time'])) {
    $lockout_time = intval(sanitize_text_field(wp_unslash($_POST['lockout_time'])));
    update_option('user_lookup_lockout_time', $lockout_time);
    $this->lockout_time = $lockout_time;
    }

    // Handle force_ssl checkbox
    if (isset($_POST['force_ssl'])) {
    update_option('user_lookup_force_ssl', true);
    } else {
    update_option('user_lookup_force_ssl', false);
    }
    }

    private function unblock_ip($ip) {
    global $wpdb;
    $wpdb->delete($this->blocked_table, array('ip_address' => $ip));
    wp_cache_delete('blocked_ips', 'secure_user_lookup'); // Clear cache after unblocking
    }

    private function permanent_block_ip($ip) {
    global $wpdb;
    $wpdb->update(
    $this->blocked_table,
    array('permanent_block' => 1),
    array('ip_address' => $ip),
    array('%d'),
    array('%s')
    );
    wp_cache_delete('blocked_ips', 'secure_user_lookup'); // Clear cache after blocking
    }

    public function register_api_endpoint() {
    register_rest_route('user-lookup/v1', '/get-username', array(
    'methods' => 'POST',
    'callback' => array($this, 'get_username'),
    'permission_callback' => array($this, 'check_permissions'),
    ));
    }

    public function get_username(WP_REST_Request $request) {
    // Extract email from the request body
    $email = $request->get_param('email');

    if (empty($email)) {
    return new WP_Error('missing_email', esc_html__('Email parameter is required', 'secure-user-lookup'), array('status' => 400));
    }

    // Find user by email
    $user = get_user_by('email', $email);

    if (!$user) {
    return new WP_Error('user_not_found', esc_html__('User not found', 'secure-user-lookup'), array('status' => 404));
    }

    // Retrieve membership level via Paid Membership Pro
    $membership_level = pmpro_getMembershipLevelForUser($user->ID);

    // Return username and membership level
    return rest_ensure_response(array(
    'data' => array(
    'username' => $user->user_login,
    'membership_level' => $membership_level ? $membership_level->name : 'None',
    ),
    ));
    }

    public function check_permissions(WP_REST_Request $request) {
    $api_key = $request->get_header('X-API-Key');
    $api_secret = $request->get_header('X-API-Secret');

    if ($api_key !== $this->api_key || $api_secret !== $this->api_secret) {
    $client_ip = isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : '';
    $this->block_ip($client_ip);
    return new WP_Error('invalid_credentials', esc_html__('Invalid API key or secret', 'secure-user-lookup'), array('status' => 403));
    }

    $client_ip = isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : '';
    $server_name = isset($_SERVER['SERVER_NAME']) ? sanitize_text_field(wp_unslash($_SERVER['SERVER_NAME'])) : '';
    $allowed = in_array($client_ip, $this->allowed_ips) || in_array($server_name, $this->allowed_domains);
    if (!$allowed) {
    $this->block_ip($client_ip);
    return new WP_Error('unauthorized', esc_html__('Access denied for your IP/domain', 'secure-user-lookup'), array('status' => 403));
    }

    // Check if IP is blocked
    if ($this->is_ip_blocked($client_ip)) {
    return new WP_Error('blocked_ip', esc_html__('Your IP is blocked', 'secure-user-lookup'), array('status' => 429));
    }

    // Check for failed attempts
    $failed_attempts = $this->get_failed_attempts($client_ip);
    if ($failed_attempts >= $this->max_failed_attempts) {
    $this->block_ip($client_ip);
    return new WP_Error('too_many_attempts', esc_html__('API locked due to too many failed attempts', 'secure-user-lookup'), array('status' => 429));
    }

    return true;
    }

    private function is_ip_blocked($ip) {
    $blocked_ips = wp_cache_get('blocked_ips', 'secure_user_lookup');
    if (false === $blocked_ips) {
    global $wpdb;
    $blocked_ips = $wpdb->get_results(
    $wpdb->prepare("SELECT * FROM " . esc_sql($this->blocked_table) . " WHERE ip_address = %s AND (blocked_until > %s OR permanent_block = 1)", $ip, gmdate('Y-m-d H:i:s'))
    );
    wp_cache_set('blocked_ips', $blocked_ips, 'secure_user_lookup', 3600); // Cache for 1 hour
    }
    return !empty($blocked_ips);
    }

    private function block_ip($ip) {
    global $wpdb;
    $time = gmdate('Y-m-d H:i:s', time() + $this->lockout_time);
    $wpdb->insert(
    $this->blocked_table,
    array(
    'ip_address' => $ip,
    'blocked_until' => $time,
    'permanent_block' => 0,
    )
    );
    wp_cache_delete('blocked_ips', 'secure_user_lookup'); // Clear cache after blocking
    }

    private function get_failed_attempts($ip) {
    $failed_attempts = wp_cache_get('failed_attempts_' . $ip, 'secure_user_lookup');
    if (false === $failed_attempts) {
    global $wpdb;
    $time = gmdate('Y-m-d H:i:s', time() - $this->lockout_time);
    $failed_attempts = $wpdb->get_var($wpdb->prepare(
    "SELECT COUNT(*) FROM " . esc_sql($this->blocked_table) . " WHERE ip_address = %s AND blocked_until > %s",
    $ip, $time
    ));
    wp_cache_set('failed_attempts_' . $ip, $failed_attempts, 'secure_user_lookup', $this->lockout_time); // Cache for lockout time
    }
    return intval($failed_attempts);
    }

    public function force_ssl_redirect() {
    if (get_option('user_lookup_force_ssl', false) && !is_ssl()) {
    $host = isset($_SERVER['HTTP_HOST']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_HOST'])) : '';
    $uri = isset($_SERVER['REQUEST_URI']) ? sanitize_text_field(wp_unslash($_SERVER['REQUEST_URI'])) : '';
    wp_redirect('https://' . $host . $uri);
    exit;
    }
    }
    }

    // Initialize plugin
    $secure_user_lookup = new SecureUserLookupAPI();
    ?>
Viewing 2 replies - 1 through 2 (of 2 total)
  • Moderator bcworkz

    (@bcworkz)

    It appears that you do use and verify nonces in the form, so the error message could be a false positive. However, I did not study your code in great detail. There could still be an issue with nonce implementation even though appropriate functions appear in your code.

    It’s true that WP functions ought to be used instead of direct SQL queries, but sometimes no WP function will suffice and you must make a direct query. “Discouraged” means the message is a suggestion, compliance is not mandatory.

    Thread Starter dronerazzo

    (@dronerazzo)

    thank you, I appreciate the time you have taken to give me some advice!

Viewing 2 replies - 1 through 2 (of 2 total)

The topic ‘Trouble with WordPress.Security.NonceVerification.Missing’ is closed to new replies.