CVE-2022-2965: Improper Restriction of Rendered UI Layers or Frames (CWE-1021)
value: Improper Restriction of Rendered UI Layers or Frames in GitHub repository notrinos/notrinoserp prior to 0.7.
CWE description: The web application does not restrict or incorrectly restricts frame objects or UI layers that belong to another application or domain, which can lead to user confusion about which interface the user is interacting with.
CVSS v3 base score: 4.3
Published: 2022-08-23T16:15Z
Repository: https://github.com/notrinos/notrinoserp
Language: PHP
Files changed: access/login.php, access/password_reset.php, includes/page/header.inc
Commit date: 2022-08-23 21:31:52 +0700
Commit message: no x-frame-options header set which allow clickjacking attack. Fixed.

Diff: diff --git a/access/login.php b/access/login.php
index 3c37245..d29e30c 100644
--- a/access/login.php
+++ b/access/login.php
@@ -50,10 +50,13 @@ $login_timeout = $_SESSION['wa_current_user']->last_act;
 $title = $login_timeout ? _('Authorization timeout') : $SysPrefs->app_title.' '.$version.' - '._('Login');
 $encoding = isset($_SESSION['language']->encoding) ? $_SESSION['language']->encoding : 'iso-8859-1';
 $rtl = isset($_SESSION['language']->dir) ? $_SESSION['language']->dir : 'ltr';
 $onload = !$login_timeout ? "onload='defaultCompany()'" : '';
 
+if (!headers_sent())
+	header("X-Frame-Options: SAMEORIGIN");
+
 echo "<!DOCTYPE html>\n";
 echo "<html dir='".$rtl."' >\n";
 echo "<head profile=\"http://www.w3.org/2005/10/profile\"><title>".$title."</title>\n";
 echo "<meta charset='".$encoding."' >\n";
 echo "<meta name='viewport' content='width=device-width,initial-scale=1'>";
diff --git a/access/password_reset.php b/access/password_reset.php
index 07c63eb..a7eb68e 100644
--- a/access/password_reset.php
+++ b/access/password_reset.php
@@ -30,10 +30,13 @@ $login_timeout = $_SESSION['wa_current_user']->last_act;
 $title = $SysPrefs->app_title.' '.$version.' - '._('Password reset');
 $encoding = isset($_SESSION['language']->encoding) ? $_SESSION['language']->encoding : 'iso-8859-1';
 $rtl = isset($_SESSION['language']->dir) ? $_SESSION['language']->dir : 'ltr';
 $onload = !$login_timeout ? "onload='defaultCompany()'" : '';
 
+if (!headers_sent())
+	header("X-Frame-Options: SAMEORIGIN");
+
 echo "<!DOCTYPE html>\n";
 echo "<html dir='".$rtl."' >\n";
 echo "<head profile=\"http://www.w3.org/2005/10/profile\"><title>".$title."</title>\n";
 echo "<meta charset='".$encoding."' >\n";
 echo "<meta name='viewport' content='width=device-width,initial-scale=1'>";
diff --git a/includes/page/header.inc b/includes/page/header.inc
index ded0e54..dc471d1 100644
--- a/includes/page/header.inc
+++ b/includes/page/header.inc
@@ -39,11 +39,11 @@ function help_url($context=null) {
 		$SysPrefs->help_base_url
 		.urlencode(strtr(ucwords($help_page_url), array(' '=>'', '/'=>'', '&'=>'And')))
 		.'&ctxhelp=1&lang='.$country);
 }
 
-function send_css($css = '') {
+function send_css($css='') {
 	global $css_files;
 
 	init_css();
 
 	foreach ($css_files as $css_file) {
@@ -117,12 +117,14 @@ function page_header($title, $no_menu=false, $is_index=false, $onload='', $js=''
 	if(isset($db_connections))	// skip before installation
 		hook_invoke_all('pre_header', $page_header_args);
 
 	$encoding = $_SESSION['language']->encoding;
 
-	if (!headers_sent())
+	if (!headers_sent()) {
 		header("Content-type: text/html; charset=$encoding");
+		header("X-Frame-Options: SAMEORIGIN");
+	}
 	
 	echo "<!DOCTYPE html>\n";
 	echo "<html dir='" . $_SESSION['language']->dir . "' >\n";
 	echo "<head profile=\"http://www.w3.org/2005/10/profile\"><title>".$title."</title>";
 	if (strpos($_SERVER['HTTP_USER_AGENT'], 'Trident/7.0; rv:11.0') != -1) // IE 11 doesn't work with input file type in form.
@@ -143,6 +145,6 @@ function page_header($title, $no_menu=false, $is_index=false, $onload='', $js=''
 
 	include_once($path_to_root.'/themes/'.$theme.'/renderer.php');
 	$rend = new renderer();
 	$rend->menu_header($title, $no_menu, $is_index);
 	error_box();
-}
\ No newline at end of file
+}

Vulnerable code: function send_css($css = '') {
	if (!headers_sent())
}
Fixed code: if (!headers_sent())
	header("X-Frame-Options: SAMEORIGIN");

if (!headers_sent())
	header("X-Frame-Options: SAMEORIGIN");

function send_css($css='') {
	if (!headers_sent()) {
		header("X-Frame-Options: SAMEORIGIN");
	}
}