CVE-2022-4867: Cross-Site Request Forgery (CSRF) (CWE-352)
value: Cross-Site Request Forgery (CSRF) in GitHub repository froxlor/froxlor prior to 2.0.0-beta1.
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: 4.3
Published: 2022-12-31T09:15Z
Repository: https://github.com/froxlor/froxlor
Language: PHP
Files changed: admin_apcuinfo.php, admin_opcacheinfo.php, lng/de.lng.php, lng/en.lng.php
Commit date: 2022-12-31 09:08:34 +0100
Commit message: fix csrf for clearing apcu/opcache cache

Signed-off-by: Michael Kaufmann <d00p@froxlor.org>

Diff: diff --git a/admin_apcuinfo.php b/admin_apcuinfo.php
index cc6046ea9..aba028071 100644
--- a/admin_apcuinfo.php
+++ b/admin_apcuinfo.php
@@ -32,24 +32,35 @@
  */
 
 use Froxlor\FroxlorLogger;
 use Froxlor\UI\Panel\UI;
 use Froxlor\UI\Response;
+use Froxlor\UI\HTML;
 
 const AREA = 'admin';
 require __DIR__ . '/lib/init.php';
 
 $horizontal_bar_size = 950; // 1280px window width
 
 if ($action == 'delete' && function_exists('apcu_clear_cache') && $userinfo['change_serversettings'] == '1') {
-	apcu_clear_cache();
-	$log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "cleared APCu cache");
-	header('Location: ' . $linker->getLink([
+	if ($_POST['send'] == 'send') {
+		apcu_clear_cache();
+		$log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "cleared APCu cache");
+		header('Location: ' . $linker->getLink([
+				'section' => 'apcuinfo',
+				'page' => 'showinfo'
+			]));
+		exit();
+	} else {
+		HTML::askYesNo('cache_reallydelete', $filename, [
+			'page' => $page,
+			'action' => 'delete',
+		], '', [
 			'section' => 'apcuinfo',
 			'page' => 'showinfo'
-		]));
-	exit();
+		]);
+	}
 }
 
 if (!function_exists('apcu_cache_info') || !function_exists('apcu_sma_info')) {
 	Response::standardError(lng('error.no_apcuinfo'));
 }
diff --git a/admin_opcacheinfo.php b/admin_opcacheinfo.php
index 37d3f5414..5c6608587 100644
--- a/admin_opcacheinfo.php
+++ b/admin_opcacheinfo.php
@@ -33,19 +33,30 @@ const AREA = 'admin';
 require __DIR__ . '/lib/init.php';
 
 use Froxlor\FroxlorLogger;
 use Froxlor\UI\Panel\UI;
 use Froxlor\UI\Response;
+use Froxlor\UI\HTML;
 
 if ($action == 'reset' && function_exists('opcache_reset') && $userinfo['change_serversettings'] == '1') {
-	opcache_reset();
-	$log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "reset OPcache");
-	header('Location: ' . $linker->getLink([
+	if ($_POST['send'] == 'send') {
+		opcache_reset();
+		$log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "reset OPcache");
+		header('Location: ' . $linker->getLink([
+				'section' => 'opcacheinfo',
+				'page' => 'showinfo'
+			]));
+		exit();
+	} else {
+		HTML::askYesNo('cache_reallydelete', $filename, [
+			'page' => $page,
+			'action' => 'reset',
+		], '', [
 			'section' => 'opcacheinfo',
 			'page' => 'showinfo'
-		]));
-	exit();
+		]);
+	}
 }
 
 if (!function_exists('opcache_get_configuration')) {
 	Response::standardError(lng('error.no_opcacheinfo'));
 }
diff --git a/lng/de.lng.php b/lng/de.lng.php
index 468e1b5c8..56b0dafaa 100644
--- a/lng/de.lng.php
+++ b/lng/de.lng.php
@@ -1277,10 +1277,11 @@ Vielen Dank, Ihr Administrator',
 		'plan_reallydelete' => 'Wollen Sie den Hostingplan %s wirklich löschen?',
 		'apikey_reallydelete' => 'Wollen Sie den Api-Key wirklich löschen?',
 		'apikey_reallyadd' => 'Einen neuen Api-Key erstellen?',
 		'dnsentry_reallydelete' => 'Wollen Sie den DNS-Eintrag wirklich löschen?',
 		'certificate_reallydelete' => 'Wollen Sie diese Zertifikat wirklich löschen?',
+		'cache_reallydelete' => 'Wollen Sie den Cache wirklich leeren?',
 	],
 	'serversettings' => [
 		'session_timeout' => [
 			'title' => 'Session-Timeout',
 			'description' => 'Wie lange muss ein Benutzer inaktiv sein, damit die Session ungültig wird? (in Sekunden)',
diff --git a/lng/en.lng.php b/lng/en.lng.php
index 952e6177e..7e3c87a1f 100644
--- a/lng/en.lng.php
+++ b/lng/en.lng.php
@@ -1389,10 +1389,11 @@ Yours sincerely, your administrator',
 		'plan_reallydelete' => 'Do you really want to delete the hosting plan %s?',
 		'apikey_reallydelete' => 'Do you really want to delete this api-key?',
 		'apikey_reallyadd' => 'Do you really want to create a new api-key?',
 		'dnsentry_reallydelete' => 'Do you really want to delete this zone entry?',
 		'certificate_reallydelete' => 'Do you really want to delete this certificate?',
+		'cache_reallydelete' => 'Do you really want to clear the cache?',
 	],
 	'redirect_desc' => [
 		'rc_default' => 'default',
 		'rc_movedperm' => 'moved permanently',
 		'rc_found' => 'found',

Vulnerable code: 	apcu_clear_cache();
	$log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "cleared APCu cache");
	header('Location: ' . $linker->getLink([
		]));
	exit();
	opcache_reset();
	$log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "reset OPcache");
	header('Location: ' . $linker->getLink([
		]));
	exit();
Fixed code: use Froxlor\UI\HTML;
	if ($_POST['send'] == 'send') {
		apcu_clear_cache();
		$log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "cleared APCu cache");
		header('Location: ' . $linker->getLink([
				'section' => 'apcuinfo',
				'page' => 'showinfo'
			]));
		exit();
	} else {
		HTML::askYesNo('cache_reallydelete', $filename, [
			'page' => $page,
			'action' => 'delete',
		], '', [
		]);
	}
use Froxlor\UI\HTML;
	if ($_POST['send'] == 'send') {
		opcache_reset();
		$log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "reset OPcache");
		header('Location: ' . $linker->getLink([
				'section' => 'opcacheinfo',
				'page' => 'showinfo'
			]));
		exit();
	} else {
		HTML::askYesNo('cache_reallydelete', $filename, [
			'page' => $page,
			'action' => 'reset',
		], '', [
		]);
	}
		'cache_reallydelete' => 'Wollen Sie den Cache wirklich leeren?',
		'cache_reallydelete' => 'Do you really want to clear the cache?',