CVE-2022-4604: Cross-Site Request Forgery (CSRF) (CWE-352)
value: A vulnerability classified as problematic was found in wp-english-wp-admin Plugin up to 1.5.1. Affected by this vulnerability is the function register_endpoints of the file english-wp-admin.php. The manipulation leads to cross-site request forgery. The attack can be launched remotely. Upgrading to version 1.5.2 is able to address this issue. The name of the patch is ad4ba171c974c65c3456e7c6228f59f40783b33d. It is recommended to upgrade the affected component. The associated identifier of this vulnerability is VDB-216199.
CWE description: The web application does not, or can not, sufficiently verify whether a well-formed, valid, consistent request was intentionally provided by the user who submitted the request.
CVSS v3 base score: 8.8
Published: 2022-12-18T11:15Z
Repository: https://github.com/khromov/wp-english-wp-admin
Language: PHP
Files changed: english-wp-admin.php, readme.txt
Commit date: 2022-02-23 23:28:03 +0100
Commit message: Fix vulnerability

Diff: diff --git a/english-wp-admin.php b/english-wp-admin.php
index 9c00d3d..954c349 100644
--- a/english-wp-admin.php
+++ b/english-wp-admin.php
@@ -1,11 +1,11 @@
 <?php
 /*
 Plugin Name: English WordPress Admin
 Plugin URI: http://wordpress.org/plugins/english-wp-admin
 Description: Lets users change their administration language to English
-Version: 1.5.1
+Version: 1.5.2
 Author: khromov
 Author URI: http://snippets.khromov.se
 GitHub Plugin URI: khromov/wp-english-wp-admin
 License: GPL2
 */
@@ -87,19 +87,21 @@ class Admin_Custom_Language
 	 */
 	function register_endpoints()
 	{
 		//We're in admin
 		if(is_admin()) {
-			//Is the GET variable set?
-			if(isset($_GET['admin_custom_language_toggle'])) {
+			
+			//Is the GET variables required set?
+			if(isset($_GET['admin_custom_language_toggle']) && isset($_GET['nonce'])) {
+
 				//Cast variable
 				$cookie_value = intval($_GET['admin_custom_language_toggle']);
 
 				//Set cookie
 				$cookie_value === 1 ? $this->set_cookie(1) : $this->set_cookie(0);
 
-				if(isset($_GET['admin_custom_language_return_url'])) {
+				if(isset($_GET['admin_custom_language_return_url']) && wp_verify_nonce( $_GET['nonce'], 'english_wordpress_admin_redirect')) {
 					wp_redirect(urldecode($_GET['admin_custom_language_return_url']));
 				}
 				else {
 					wp_redirect(admin_url());
 				}
@@ -252,16 +254,19 @@ class Admin_Custom_Language
 	 */
 	function admin_bar($wp_admin_bar)
 	{
 		//We're in admin and this is not a WPML install
 		if(is_admin() && apply_filters('english_wordpress_admin_show_admin_bar', true) === true) {
+			
 			//Sets up the toggle link
+			$toggle_nonce = wp_create_nonce('english_wordpress_admin_redirect');
+
 			if($this->in_url_whitelist()) {
 				$toggle_href =  plugin_dir_url( __FILE__ ) . 'readme.txt';
 			}
 			else {
-				$toggle_href = admin_url('?admin_custom_language_toggle=' . ($this->english_admin_enabled() ? '0' : '1') . '&admin_custom_language_return_url=' . urlencode((is_ssl() ? 'https' : 'http') . '://' . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]));
+				$toggle_href = admin_url('?admin_custom_language_toggle=' . ($this->english_admin_enabled() ? '0' : '1') . '&nonce=' . $toggle_nonce . '&admin_custom_language_return_url=' . urlencode((is_ssl() ? 'https' : 'http') . '://' . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]));
 			}
 
 			//Create toggle title
 			if($this->in_url_whitelist()) {
 				$toggle_title = __('This admin screen cannot be translated. For more information, see the readme.', self::SLUG);
diff --git a/readme.txt b/readme.txt
index d88e315..cda1f4b 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,11 +1,11 @@
 === English WordPress Admin ===
 Contributors: khromov
 Tags: english, wpml, multilanguage
 Requires at least: 3.5
 Tested up to: 5.3
-Stable tag: 1.5.1
+Stable tag: 1.5.2
 License: GPL2
 
 Lets users change their administration language to English
 
 == Description ==
@@ -98,10 +98,14 @@ You can leave feature requests in the plugin support forum.
 
 1. The plugin admin bar
 
 == Changelog ==
 
+= 1.5.2 =
+
+* Fix for unauthenticated open redirect vulnerability
+
 = 1.5.1 =
 
 * Fix for PHP 5.2
 * Fix for whitelisting edge case
 * Code formatting touchup

Vulnerable code: Version: 1.5.1
			//Is the GET variable set?
			if(isset($_GET['admin_custom_language_toggle'])) {
				if(isset($_GET['admin_custom_language_return_url'])) {
				$toggle_href = admin_url('?admin_custom_language_toggle=' . ($this->english_admin_enabled() ? '0' : '1') . '&admin_custom_language_return_url=' . urlencode((is_ssl() ? 'https' : 'http') . '://' . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]));
Stable tag: 1.5.1
Fixed code: Version: 1.5.2
			
			//Is the GET variables required set?
			if(isset($_GET['admin_custom_language_toggle']) && isset($_GET['nonce'])) {

				if(isset($_GET['admin_custom_language_return_url']) && wp_verify_nonce( $_GET['nonce'], 'english_wordpress_admin_redirect')) {
			
			$toggle_nonce = wp_create_nonce('english_wordpress_admin_redirect');

				$toggle_href = admin_url('?admin_custom_language_toggle=' . ($this->english_admin_enabled() ? '0' : '1') . '&nonce=' . $toggle_nonce . '&admin_custom_language_return_url=' . urlencode((is_ssl() ? 'https' : 'http') . '://' . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]));
Stable tag: 1.5.2
= 1.5.2 =

* Fix for unauthenticated open redirect vulnerability