CVE-2021-3258: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: Question2Answer Q2A Ultimate SEO Version 1.3 is affected by cross-site scripting (XSS), which may lead to arbitrary remote code execution.
CWE description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVSS v3 base score: 5.4
Published: 2021-02-05T16:15Z
Repository: https://github.com/q2a-projects/Q2A-Ultimate-SEO
Language: PHP
Files changed: q2a-ultimate-seo/layer.php
Commit date: 2017-07-15 19:45:35 -0800
Commit message: Sanitizing Meta output

Diff: diff --git a/q2a-ultimate-seo/layer.php b/q2a-ultimate-seo/layer.php
index 6ed14d8..2c273e9 100644
--- a/q2a-ultimate-seo/layer.php
+++ b/q2a-ultimate-seo/layer.php
@@ -10,31 +10,31 @@ class qa_html_theme_layer extends qa_html_theme_base {
 		qa_html_theme_base::doctype();
 		require_once QA_INCLUDE_DIR.'qa-db-metas.php';
 		// Custom Meta(title,description,keywords)
 		if( ($this->template=='question') and (qa_opt('useo_meta_editor_enable')) ){
 			$metas = json_decode(qa_db_postmeta_get($this->content['q_view']['raw']['postid'], 'useo-meta-info'),true);
-			$this->meta_title = @$metas['title'];
-			$this->meta_description = @$metas['description'];
-			$this->meta_keywords = @$metas['keywords'];
+			$this->meta_title = htmlspecialchars(@$metas['title']);
+			$this->meta_description = htmlspecialchars(@$metas['description']);
+			$this->meta_keywords = htmlspecialchars(@$metas['keywords']);
 		}
 		// Generate Social Meta Tags
 		$page_url = @$this->content['canonical'];
 		if(! empty($this->meta_description))
-			$description = $this->meta_description;
+			$description = htmlspecialchars($this->meta_description);
 		else
-			$description = @$this->content['description'];
+			$description = htmlspecialchars(@$this->content['description']);
 		if(! empty($this->meta_title))
-			$title = $this->meta_title;
+			$title = htmlspecialchars($this->meta_title);
 		else
-			$title = @$this->content['q_view']['raw']['title'];
+			$title = htmlspecialchars(@$this->content['q_view']['raw']['title']);
 		
 		if($this->template=='question'){
 			if(qa_opt('useo_social_enable_editor')){
 				$this->social_metas = json_decode(qa_db_postmeta_get($this->content['q_view']['raw']['postid'], 'useo-social-info'),true);
 				if(count($this->social_metas))
 					foreach ($this->social_metas as $index => $variable){
-						$this->metas[$index]['content'] = $variable;
+						$this->metas[$index]['content'] = htmlspecialchars($variable);
 						$this->metas[$index]['type'] = '';
 					}
 			}
 			if(qa_opt('useo_social_og_enable_auto')){ // Open Graph
 				// site name
@@ -72,11 +72,11 @@ class qa_html_theme_layer extends qa_html_theme_base {
 				$this->metas['tc-title']['content'] = $title;
 				$this->metas['tc-title']['type'] = 'property="twitter:title"';
 				// description
 				$useo_social_tc_desc_length = qa_opt('useo_social_og_desc_length');
 				if($useo_social_tc_desc_length<=0)
-						$useo_social_tc_desc_length = 120;
+					$useo_social_tc_desc_length = 120;
 				$this->metas['tc-description']['content'] = useo_get_excerpt($description, 0, $useo_social_tc_desc_length);
 				$this->metas['tc-description']['type'] = 'property="twitter:description"';
 				// image
 				$tc_image = qa_opt('useo_social_tc_image');
 				if(! empty($tc_image)){
@@ -221,11 +221,11 @@ class qa_html_theme_layer extends qa_html_theme_base {
 				if(empty($this->meta_title)){
 					// title customization
 					$title_template = qa_opt('useo_title_qa_item');
 					if(! empty($title_template) ){
 						$search = array( '%site-title%', '%question-title%', '%category-name%');
-						$replace   = array(qa_opt('site_title'), @$this->content['q_view']['raw']['title'], $category_name);
+						$replace   = array(qa_opt('site_title'), htmlspecialchars(@$this->content['q_view']['raw']['title']), $category_name);
 						$title = str_replace($search, $replace, $title_template);
 					}
 				}else{
 					// meta editor
 					$title = $this->meta_title;
@@ -428,14 +428,14 @@ class qa_html_theme_layer extends qa_html_theme_base {
 		}
 	// Question Meta tags
 		if($this->template=='question'){
 			// setup custom meta keyword
 			if (! empty($this->meta_keywords))
-				$this->content['keywords'] = $this->meta_keywords;
+				$this->content['keywords'] = htmlspecialchars($this->meta_keywords);
 			// setup custom meta description
 			if (! empty($this->meta_description))
-				$this->content['description'] = $this->meta_description;
+				$this->content['description'] = htmlspecialchars($this->meta_description);
 			// if there was no custom meta description and it's supposed to read it from answers do it, otherwise don't change it
 			elseif(qa_opt('useo_meta_desc_ans_enable')){
 				$lenght = (int)qa_opt('useo_meta_desc_length');
 				if($lenght<=0)
 					$lenght = 160;
@@ -497,11 +497,11 @@ class qa_html_theme_layer extends qa_html_theme_base {
 							Page Title
 						</td>
 					</tr>
 					<tr>
 						<td class="qa-form-tall-data">
-							<input placeholder="' . $this->content['q_view']['raw']['title'] . '" id="useo-meta-editor-title" class="qa-form-tall-text" type="text" value="'. $this->meta_title .'" name="useo-meta-editor-title">
+							<input placeholder="' . htmlspecialchars($this->content['q_view']['raw']['title']) . '" id="useo-meta-editor-title" class="qa-form-tall-text" type="text" value="'. $this->meta_title .'" name="useo-meta-editor-title">
 						</td>
 					</tr>
 				</tbody>
 
 				<tbody>
@@ -510,11 +510,11 @@ class qa_html_theme_layer extends qa_html_theme_base {
 							Description Meta Tag
 						</td>
 					</tr>
 					<tr>
 						<td class="qa-form-tall-data">
-							<textarea placeholder="' . $this->content['description'] . '" id="useo-meta-editor-description" class="qa-form-tall-text" cols="40" rows="3" name="useo-meta-editor-description">'. $this->meta_description .'</textarea>
+							<textarea placeholder="' . htmlspecialchars($this->content['description']) . '" id="useo-meta-editor-description" class="qa-form-tall-text" cols="40" rows="3" name="useo-meta-editor-description">'. $this->meta_description .'</textarea>
 						</td>
 					</tr>
 				</tbody>
 				<tbody id="useo-meta-keywords">
 					<tr>

Vulnerable code: 			$this->meta_title = @$metas['title'];
			$this->meta_description = @$metas['description'];
			$this->meta_keywords = @$metas['keywords'];
			$description = $this->meta_description;
			$description = @$this->content['description'];
			$title = $this->meta_title;
			$title = @$this->content['q_view']['raw']['title'];
						$this->metas[$index]['content'] = $variable;
						$useo_social_tc_desc_length = 120;
						$replace   = array(qa_opt('site_title'), @$this->content['q_view']['raw']['title'], $category_name);
				$this->content['keywords'] = $this->meta_keywords;
				$this->content['description'] = $this->meta_description;
							<input placeholder="' . $this->content['q_view']['raw']['title'] . '" id="useo-meta-editor-title" class="qa-form-tall-text" type="text" value="'. $this->meta_title .'" name="useo-meta-editor-title">
							<textarea placeholder="' . $this->content['description'] . '" id="useo-meta-editor-description" class="qa-form-tall-text" cols="40" rows="3" name="useo-meta-editor-description">'. $this->meta_description .'</textarea>
Fixed code: 			$this->meta_title = htmlspecialchars(@$metas['title']);
			$this->meta_description = htmlspecialchars(@$metas['description']);
			$this->meta_keywords = htmlspecialchars(@$metas['keywords']);
			$description = htmlspecialchars($this->meta_description);
			$description = htmlspecialchars(@$this->content['description']);
			$title = htmlspecialchars($this->meta_title);
			$title = htmlspecialchars(@$this->content['q_view']['raw']['title']);
						$this->metas[$index]['content'] = htmlspecialchars($variable);
					$useo_social_tc_desc_length = 120;
						$replace   = array(qa_opt('site_title'), htmlspecialchars(@$this->content['q_view']['raw']['title']), $category_name);
				$this->content['keywords'] = htmlspecialchars($this->meta_keywords);
				$this->content['description'] = htmlspecialchars($this->meta_description);
							<input placeholder="' . htmlspecialchars($this->content['q_view']['raw']['title']) . '" id="useo-meta-editor-title" class="qa-form-tall-text" type="text" value="'. $this->meta_title .'" name="useo-meta-editor-title">
							<textarea placeholder="' . htmlspecialchars($this->content['description']) . '" id="useo-meta-editor-description" class="qa-form-tall-text" cols="40" rows="3" name="useo-meta-editor-description">'. $this->meta_description .'</textarea>