24 Feb 2025

Settings Change and Persistent Cross-Site Scripting (XSS) Vulnerabilities in Donate visa

Today we saw what appeared to be a hacker probing for usage of the WordPress plugin Donate visa in third-party data we monitor. The probing was done by requesting a file from the plugin if the plugin had existed on a website, /wp-content/plugins/donate-visa/readme.txt. The plugin was closed on the WordPress Plugin Directory on November 5, 2024. The reason given for the closure is “Security Issue.” Nothing was provided to vet the claim there was a security issue. Competitors of ours have claimed there is an unfixed vulnerability that allows attackers “with Subscriber-level access and above, to perform an unauthorized action.” They provided nothing to back that up. Looking at the code, we found what they appear to be referring to, but as is so often the case, they didn’t bother to do proper vetting and got a basic detail wrong. The real vulnerability is one you would expect to be exploited.

The only code that looks like it could be related to the claimed vulnerability is the code that handles saving the plugin’s settings. That is handled by the function donate_visa_dvsmp_ajax() in the file /includes/class-donate-visa-dvsmp-plugin.php. That doesn’t include any security checks:

130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
public function donate_visa_dvsmp_ajax()
{
	if (!empty($_POST)){
 
		if(!empty($_POST['donate-visa-enviroment-dvsmp'])){
			update_option('donate-visa-enviroment-dvsmp', sanitize_text_field($_POST['donate-visa-enviroment-dvsmp']));
			update_option('donate-visa-currency-dvsmp', sanitize_text_field($_POST['donate-visa-currency-dvsmp']));
			update_option('donate-visa-apikey-dvsmp', sanitize_text_field($_POST['donate-visa-apikey-dvsmp']));
		}
 
		if (!empty($_POST['company'])){
 
			$payments = get_option('donate-visa-dvsmp-payments');
			$transaction = array(array('name' => sanitize_text_field($_POST['name']), 'company' => sanitize_text_field($_POST['company']), 'price' => sanitize_text_field($_POST['price']), 'currencyCode' => sanitize_text_field($_POST['currencyCode']),  'email' => sanitize_text_field($_POST['email'])));
 
			if (empty($payments)){
				update_option('donate-visa-dvsmp-payments', $transaction);
			}else{
			   $array = array_merge($payments, $transaction);
				update_option('donate-visa-dvsmp-payments', $array);
			}
 
		}
	}
	die();
}

Who can access that? Well, the function is registered to be accessible to anyone logged in to WordPress through its AJAX functionality:

63
add_action( 'wp_ajax_donate_visa_dvsmp',array($this,'donate_visa_dvsmp_ajax'));

That would provide access to those logged in as Subscribers and above, which matches the claim made by our competitors.But the line right below that one in the code makes it available to those not even logged in:

64
add_action( 'wp_ajax_nopriv_donate_visa_dvsmp',array($this,'donate_visa_dvsmp_ajax'));

So anyone can change the plugin’s settings. One of the implications of this is that an attacker can cause malicious JavaScript code to run on an admin page of the website. That is because the user input being saved is sanitized using sanitize_text_field(), but at least one of the inputs is then output as an HTML attribute, which sanitize_text_field() doesn’t sanitize input for. That is what is referred to as a persistent cross-site scripting (XSS) vulnerability and hackers are very interested in targeting that.

Free Warning

As the latter vulnerability looks to be targeted by hackers, we are adding accurate data on it to the free data that comes with our Plugin Vulnerabilities plugin.

Leave a Reply

Your email address will not be published. Required fields are marked *