Analysis Report backuply 1.3.4 → 1.3.5 - CVE-2024-8669

Shared security patch analysis results

AI Used: deepseek deepseek-reasoner
Share this analysis
Use quotes for exact: \"SQL injection\" | Operators: hello AND bye, admin OR root, -error, NOT warning
Showing 0 to 0 of 0 results
backup_ins.php AI: 1 vulnerabilities 1 true positive
--- cache/backuply_1.3.4/backup_ins.php	2025-11-16 19:18:31.781788288 +0000+++ cache/backuply_1.3.5/backup_ins.php	2025-11-16 19:20:40.251036257 +0000@@ -5,6 +5,10 @@ * (c) Backuply Team */ +if(!defined('ABSPATH')){+	die('HACKING ATTEMPT!');+}+ //PHP Options if(!set_time_limit(300)){ 	set_time_limit(60);
AI Analysis
Vulnerability Existed: yes  
TRUE POSITIVE
Improper Access Control - CWE-284 - backup_ins.php [Lines 5-8]  
Old Code:  
```
/*
* Backuply Backup Installation file
* (c) Backuply Team
*/

//PHP Options
if(!set_time_limit(300)){
	set_time_limit(60);
```  
Fixed Code:  
```
/*
* Backuply Backup Installation file
* (c) Backuply Team
*/

if(!defined('ABSPATH')){
	die('HACKING ATTEMPT!');
}

//PHP Options
if(!set_time_limit(300)){
	set_time_limit(60);
```  
Explanation: The old code lacked a direct access prevention check, allowing the file to be accessed directly via URL without WordPress context. This could enable unauthorized users to execute sensitive backup operations or other functionality, bypassing WordPress authentication and security mechanisms (e.g., nonce verification). The fixed code adds an ABSPATH check, which terminates execution if not defined, ensuring the file is only accessible within WordPress where proper security controls are enforced.
CVE Analysis Results:
CVE-2024-8669: No
View CVE Description
The Backuply – Backup, Restore, Migrate and Clone plugin for WordPress is vulnerable to SQL Injection via the 'options' parameter passed to the backuply_wp_clone_sql() function in all versions up to, and including, 1.3.4 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for authenticated attackers, with administrator-level access and above, to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.
backuply.php AI: No vulnerabilities
--- cache/backuply_1.3.4/backuply.php	2025-11-16 19:18:31.781788288 +0000+++ cache/backuply_1.3.5/backuply.php	2025-11-16 19:20:40.251036257 +0000@@ -3,7 +3,7 @@ Plugin Name: Backuply
 Plugin URI: http://wordpress.org/plugins/backuply/
 Description: Backuply is a Wordpress Backup plugin. Backups are the best form of security and safety a website can have.
-Version: 1.3.4
+Version: 1.3.5
 Author: Softaculous
 Author URI: https://backuply.com
 License: LGPL v2.1
AI Analysis
No vulnerabilities are detected in the provided diff for the file backuply.php. The change only involves updating the version number from 1.3.4 to 1.3.5, which does not affect any code logic, user input handling, or security-sensitive sinks. Therefore, no security issues are introduced or fixed in this specific diff snippet.
CVE Analysis Results:
CVE-2024-8669: No
View CVE Description
The Backuply – Backup, Restore, Migrate and Clone plugin for WordPress is vulnerable to SQL Injection via the 'options' parameter passed to the backuply_wp_clone_sql() function in all versions up to, and including, 1.3.4 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for authenticated attackers, with administrator-level access and above, to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.
functions.php AI: 1 vulnerabilities 1 true positive CVE-2024-8669
--- cache/backuply_1.3.4/functions.php	2025-11-16 19:18:31.783788416 +0000+++ cache/backuply_1.3.5/functions.php	2025-11-16 19:20:40.252036321 +0000@@ -218,7 +218,7 @@ 	$config = backuply_get_config(); 	 	if(!empty($restore_key)){-		if(urldecode($key) == $config['RESTORE_KEY']) {+		if(!empty($config['RESTORE_KEY']) && urldecode($key) == $config['RESTORE_KEY']) { 			return true; 		} 		@@ -275,7 +275,7 @@ function backuply_set_config() { 	 	$write['BACKUPLY_KEY'] = backuply_csrf_get_token();-	$write['RESTORE_KEY'] = backuply_csrf_get_token();+	// $write['RESTORE_KEY'] = backuply_csrf_get_token(); 	 	update_option('backuply_config_keys', $write); }@@ -1471,20 +1471,33 @@ 	 } -- //Fix the serialization in Cloned DB Tables function backuply_wp_clone_sql($table, $field_prefix, $keepalive, $i = null){  	global $wpdb;-	+ 	if(empty($wpdb)){ 		backuply_log('Fix Serialization failed: unable to connect to the database'); 		return false; 	} 	-	$cnt_qry = "SELECT count('".$field_prefix."_id') as count_".$field_prefix." FROM `".$wpdb->prefix.$table . "`;";+	if(empty($table) || empty($field_prefix)){+		return false;+	}+	+	$possible_tables = ['options', 'postmeta', 'commentmeta'];+	$possible_fields = ['option', 'meta']; +	// We make sure here that we do not process any unwanted data.+	if(!in_array($table, $possible_tables, true) || !in_array($field_prefix, $possible_fields, true)){+		return false;+	}++	if($wpdb->has_cap('identifier_placeholders')){+		$cnt_qry = $wpdb->prepare("SELECT count(%i) as %i FROM %i", [$field_prefix.'_id', 'count_'.$field_prefix, $wpdb->prefix.$table]);+	} else {+		$cnt_qry = $wpdb->prepare("SELECT count(%s) as %s FROM `".$wpdb->prefix.$table . "`", [$field_prefix.'_id', 'count_'.$field_prefix]);+	} 	$result = $wpdb->get_results($cnt_qry); 	$result = json_decode(json_encode($result[0]), true); 	$cnt_res = $result['count_'.$field_prefix];@@ -1492,12 +1505,8 @@ 	$count = 10000; 	$limit = 0; -	$org_query = "SELECT `".$field_prefix."_id`, `".$field_prefix."_value` FROM `".$wpdb->prefix.$table."` ORDER BY ".$field_prefix."_id";-	-	 	if(is_null($i)){ 		$i = $cnt_res;-		 		backuply_status_log('Repairing '. $wpdb->prefix.$table, 'repairing', 80); 	} 	@@ -1508,12 +1517,15 @@ 		if(time() > $keepalive){ 			return (int) $i; 		}-		-		$query = $org_query.' LIMIT '.$limit.', '.$count.';';-		++		if($wpdb->has_cap('identifier_placeholders')){+			$query = $wpdb->prepare("SELECT %i, %i FROM %i ORDER BY %i LIMIT %d, %d", [$field_prefix.'_id', $field_prefix.'_value', $wpdb->prefix.$table, $field_prefix.'_id', $limit, $count]);+		} else {+			$query = $wpdb->prepare("SELECT `".$field_prefix."_id`, `".$field_prefix."_value` FROM `".$wpdb->prefix.$table."` ORDER BY %s LIMIT %d, %d", [$field_prefix.'_id', $limit, $count]);+		}+ 		$result = $wpdb->get_results($query); 		-		 		// If there are no more rows we need to break the loop 		if(empty($result[0])){ 			break;@@ -1544,12 +1556,11 @@ 				 				$sresult = $wpdb->query($update_query); 			}++			$i--;+			$limit++; 		}-		-		$i--; 	}--	$limit = $limit + $count; 	 	return true; }@@ -1719,6 +1730,9 @@ // Shifts the Config keys from file to db for user below 1.2.0. function backuply_keys_to_db(){ 	$config = backuply_get_config();+	if(isset($config['RESTORE_KEY'])){+		unset($config['RESTORE_KEY']); // Restore Key gets generated every time a restore is created.+	}  	update_option('backuply_config_keys', $config); 	unlink(BACKUPLY_BACKUP_DIR . '/backuply_config.php');
AI Analysis
Vulnerability Existed: yes  
TRUE POSITIVE
CWE-89: Improper Neutralization of Special Elements used in an SQL Command - functions.php [1471-1491]  
Old Code:  
```php
$cnt_qry = "SELECT count('".$field_prefix."_id') as count_".$field_prefix." FROM `".$wpdb->prefix.$table . "`;";
$org_query = "SELECT `".$field_prefix."_id`, `".$field_prefix."_value` FROM `".$wpdb->prefix.$table."` ORDER BY ".$field_prefix."_id";
$query = $org_query.' LIMIT '.$limit.', '.$count.';';
```  
Fixed Code:  
```php
if(empty($table) || empty($field_prefix)){
    return false;
}

$possible_tables = ['options', 'postmeta', 'commentmeta'];
$possible_fields = ['option', 'meta'];

if(!in_array($table, $possible_tables, true) || !in_array($field_prefix, $possible_fields, true)){
    return false;
}

if($wpdb->has_cap('identifier_placeholders')){
    $cnt_qry = $wpdb->prepare("SELECT count(%i) as %i FROM %i", [$field_prefix.'_id', 'count_'.$field_prefix, $wpdb->prefix.$table]);
} else {
    $cnt_qry = $wpdb->prepare("SELECT count(%s) as %s FROM `".$wpdb->prefix.$table . "`", [$field_prefix.'_id', 'count_'.$field_prefix]);
}

// Similarly for the query in the loop using $wpdb->prepare
```  
Explanation:  
In the old code, the parameters `$table` and `$field_prefix` were directly concatenated into SQL queries without sanitization. If an attacker controlled these values (e.g., through crafted backup data or other inputs), they could manipulate the query structure to execute arbitrary SQL commands. The sink is the SQL query execution via `$wpdb->get_results` and `$wpdb->query`.  
In the new code, a whitelist restricts `$table` to `['options', 'postmeta', 'commentmeta']` and `$field_prefix` to `['option', 'meta']`, ensuring only safe values are used. Additionally, `$wpdb->prepare` with placeholders (`%i` for identifiers or `%s` for strings) is employed, which properly neutralizes input and prevents SQL injection. The taint flow is broken by these defenses.
CVE Analysis Results:
CVE-2024-8669: Yes
View CVE Description
The Backuply – Backup, Restore, Migrate and Clone plugin for WordPress is vulnerable to SQL Injection via the 'options' parameter passed to the backuply_wp_clone_sql() function in all versions up to, and including, 1.3.4 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for authenticated attackers, with administrator-level access and above, to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.
init.php AI: No vulnerabilities 1 true positive
--- cache/backuply_1.3.4/init.php	2025-11-16 19:18:31.783788416 +0000+++ cache/backuply_1.3.5/init.php	2025-11-16 19:20:40.253036385 +0000@@ -10,7 +10,7 @@ 	exit;
 }
 
-define('BACKUPLY_VERSION', '1.3.4');
+define('BACKUPLY_VERSION', '1.3.5');
 define('BACKUPLY_DIR', dirname(BACKUPLY_FILE));
 define('BACKUPLY_URL', plugins_url('', BACKUPLY_FILE));
 define('BACKUPLY_BACKUP_DIR', str_replace('\\' , '/', WP_CONTENT_DIR).'/backuply/');
AI Analysis
Vulnerability Existed: no  
N/A - N/A - init.php 13  
Old Code: `define('BACKUPLY_VERSION', '1.3.4');`  
Fixed Code: `define('BACKUPLY_VERSION', '1.3.5');`  
Explanation: This change updates the version constant from 1.3.4 to 1.3.5. There is no user input, data flow, or security-sensitive code modified. The version string is hard-coded and does not interact with any sinks or involve any validation, sanitization, or taint tracing. Therefore, no vulnerability is introduced or fixed by this change.
CVE Analysis Results:
CVE-2024-8669: No
View CVE Description
The Backuply – Backup, Restore, Migrate and Clone plugin for WordPress is vulnerable to SQL Injection via the 'options' parameter passed to the backuply_wp_clone_sql() function in all versions up to, and including, 1.3.4 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for authenticated attackers, with administrator-level access and above, to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.
main/ajax.php AI: No vulnerabilities
--- cache/backuply_1.3.4/main/ajax.php	2025-11-16 19:18:31.788788737 +0000+++ cache/backuply_1.3.5/main/ajax.php	2025-11-16 19:20:40.256036578 +0000@@ -322,7 +322,7 @@ 	 	$keepalive = (int) time() + 25; -	if(!backuply_verify_self(backuply_optreq('security'))){+	if(!backuply_verify_self(backuply_optreq('security'), true)){ 		backuply_status_log('Security Check Failed', 'error'); 		die(); 	}@@ -331,8 +331,9 @@ 		$session_data = array('time' => time(), 'key' => backuply_optreq('sess_key'), 'user_id' => backuply_optreq('user_id')); 	 		update_option('backuply_restore_session_key', $session_data, false);-		 		backuply_status_log('Repairing database serialization', 'info', 78);++		// NOTE:: If you add any table here make sure to update the same in the backuply_wp_clone_sql function as well. 		$clones = ['options' => 'option', 'postmeta' => 'meta', 'commentmeta' => 'meta']; 		backuply_update_serialization($keepalive, $clones); 	}@@ -413,7 +414,7 @@ 	backuply_delete_rinfo_on_restore(); 	backuply_copy_log_file(true); 	backuply_clean_restoration_file();-	+ 	die(); } @@ -423,7 +424,6 @@ 	if(!function_exists('backuply_wp_clone_sql')){ 		include_once BACKUPLY_DIR . '/functions.php'; 	}-	  	$keys = array_keys($options); 	$repair_log = get_option('backuply_sql_repair_log');@@ -437,9 +437,11 @@  	if(!is_numeric($res)) { 		delete_option('backuply_sql_repair_log');-		unset($options[$keys[0]]);+		if(isset($options[$keys[0]])){+			unset($options[$keys[0]]);+		} 	}-	+ 	if($res === false){ 		backuply_status_log('Something went wrong while repairing database', 'error'); 		die();@@ -452,8 +454,8 @@ 	} 	 	$config = backuply_get_config();-	if(empty($config['BACKUPLY_KEY'])){-		backuply_status_log('Backuply key not found!', 'error');+	if(empty($config['RESTORE_KEY'])){+		backuply_status_log('Restore key not found!', 'error'); 		die(); 	} 	@@ -476,7 +478,7 @@ 		$body['i'] = $res; 	} 	-	$url = admin_url('admin-ajax.php'). '?action=backuply_update_serialization&security='. $config['BACKUPLY_KEY'];+	$url = admin_url('admin-ajax.php'). '?action=backuply_update_serialization&security='. $config['RESTORE_KEY']; 	 	wp_remote_post($url, array( 		'body' => $body,@@ -492,7 +494,7 @@ function backuply_update_serialization_ajax() {  	//Security Check-	if(!backuply_verify_self(backuply_optreq('security'))){+	if(!backuply_verify_self(backuply_optreq('security'), true)){ 		backuply_status_log('Security Check Failed', 'error'); 		die(); 	}@@ -502,10 +504,10 @@ 	 	$keepalive = time() + 25; +	$i = !empty(backuply_optpost('i')) ? (int) backuply_optpost('i') : null;+	$options = map_deep(wp_unslash($_POST['options']), 'sanitize_text_field'); 	-	$i = !empty(backuply_optpost('i')) ? backuply_optpost('i') : null;-	-	backuply_update_serialization($keepalive, sanitize_post($_POST['options']) ,$i);+	backuply_update_serialization($keepalive, $options, $i); }  function backuply_get_restore_key(){@@ -537,7 +539,7 @@ function backuply_creating_session(){ 	 	// Security Check-	if(!backuply_verify_self(backuply_optreq('security'))){+	if(!backuply_verify_self(backuply_optreq('security'), true)){ 		backuply_status_log('Security Check Failed', 'error'); 		die(); 	}@@ -573,7 +575,7 @@ 		$username = $user->user_login; 		$user = get_user_by('login', $username); 	}-	+ 	if(isset($user) && is_object($user) && property_exists($user, 'ID')){ 		clean_user_cache(get_current_user_id()); 		clean_user_cache($user->ID);
AI Analysis
After analyzing the diff content for the file `main/ajax.php` between versions 1.3.4 and 1.3.5, I performed explicit taint tracing for potential vulnerabilities. The key changes involve security checks, input sanitization, and SQL serialization repair logic. Below is the analysis based on the provided code context and diff.

### Taint Tracing Summary:
- **Entry Points**: User input via `$_REQUEST`, `$_POST`, and `$_GET` parameters (e.g., `security`, `options`, `i`, `error_string`).
- **Transformations/Validations**: 
  - Inputs are passed through `backuply_optreq`, `backuply_optpost`, or `backuply_optget`, which apply `trim`, `backuply_htmlizer`, and `backuply_inputsec` (assumed sanitization functions).
  - Specific parameters are further sanitized: 
    - `security` is verified via `backuply_verify_self` against a secret key (RESTORE_KEY or BACKUPLY_KEY).
    - `options` array is sanitized using `map_deep` with `sanitize_text_field` (new in 1.3.5) or `sanitize_post` (old).
    - `i` is cast to `(int)` (new in 1.3.5).
  - SQL queries use `$wpdb->prepare` with bound parameters or whitelisted table/field names.
- **Sinks**: 
  - SQL queries in `backuply_wp_clone_sql` (using concatenation but with whitelisted inputs).
  - File operations (e.g., `file_put_contents` in `backuply_status_log`) with hardcoded or system-generated data.
  - Email output in `backuply_restore_response` with decoded error strings but protected by security checks.
- **Why Safe**: 
  - Security checks (`backuply_verify_self`) prevent unauthorized access by requiring a secret key.
  - Inputs for SQL (e.g., `table`, `field_prefix`) are whitelisted to specific values (`options`, `postmeta`, `commentmeta`, `option`, `meta`).
  - Sanitization functions (e.g., `sanitize_text_field`, casting to int) effectively neutralize injection attempts.
  - No unsanitized user input reaches sinks exploitably due to layered defenses.

No vulnerabilities were found in the diff. The changes improve security by using more appropriate sanitization and correct key verification, but no exploitable issues exist.

### Final Answer:
No vulnerabilities identified. The code changes enhance security without introducing new flaws.
CVE Analysis Results:
CVE-2024-8669: No
View CVE Description
The Backuply – Backup, Restore, Migrate and Clone plugin for WordPress is vulnerable to SQL Injection via the 'options' parameter passed to the backuply_wp_clone_sql() function in all versions up to, and including, 1.3.4 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for authenticated attackers, with administrator-level access and above, to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.
restore_ins.php AI: No vulnerabilities 1 true positive
--- cache/backuply_1.3.4/restore_ins.php	2025-11-16 19:18:31.792788994 +0000+++ cache/backuply_1.3.5/restore_ins.php	2025-11-16 19:20:40.259036771 +0000@@ -2856,13 +2856,13 @@ 	$config = backuply_get_config(); 	$url = $output['ajax_url']; -	if(empty($config['BACKUPLY_KEY'])) {+	if(empty($config['RESTORE_KEY'])) { 		backuply_status_log('Unable to find security key', 'error'); 		backuply_kill_process(); 		return; 	} -	$url .= '?action=backuply_restore_response&security='. $config['BACKUPLY_KEY'].'&user_id='.$output['user_id']. '&sess_key='.$output['sess_key'];+	$url .= '?action=backuply_restore_response&security='. $config['RESTORE_KEY'].'&user_id='.$output['user_id']. '&sess_key='.$output['sess_key']; 	if(!empty($output['restore_db'])){ 		$url .= '&restore_db=true'; 	}
AI Analysis
Vulnerability Existed: no  
No vulnerability found - restore_ins.php lines 2856-2865  
Old Code:  
```php
if(empty($config['BACKUPLY_KEY'])) {
	backuply_status_log('Unable to find security key', 'error');
	backuply_kill_process();
	return;
}

$url .= '?action=backuply_restore_response&security='. $config['BACKUPLY_KEY'].'&user_id='.$output['user_id']. '&sess_key='.$output['sess_key'];
```  
Fixed Code:  
```php
if(empty($config['RESTORE_KEY'])) {
	backuply_status_log('Unable to find security key', 'error');
	backuply_kill_process();
	return;
}

$url .= '?action=backuply_restore_response&security='. $config['RESTORE_KEY'].'&user_id='.$output['user_id']. '&sess_key='.$output['sess_key'];
```  
Explanation:  
The change replaces the configuration key from 'BACKUPLY_KEY' to 'RESTORE_KEY' in the URL construction and emptiness check. The security key is derived from the server-side configuration via `backuply_get_config()`, not from user input, so it is not attacker-controlled. The values for `user_id` and `sess_key` are from the `$output` array, which is not shown to be user-controlled in the provided context. The URL construction does not use URL encoding, but the keys and identifiers are expected to be alphanumeric or safely managed by the system. No specific vulnerability (e.g., injection or access control bypass) is introduced or fixed by this change; it appears to be a refactor or isolation of keys for different operations.
CVE Analysis Results:
CVE-2024-8669: No
View CVE Description
The Backuply – Backup, Restore, Migrate and Clone plugin for WordPress is vulnerable to SQL Injection via the 'options' parameter passed to the backuply_wp_clone_sql() function in all versions up to, and including, 1.3.4 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for authenticated attackers, with administrator-level access and above, to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.