CVE-2021-4271: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: A vulnerability was found in panicsteve w2wiki. It has been rated as problematic. Affected by this issue is the function toHTML of the file index.php of the component Markdown Handler. The manipulation leads to cross site scripting. The attack may be launched remotely. The name of the patch is 8f1d0470b4ddb1c7699e3308e765c11ed29542b6. It is recommended to apply a patch to fix this issue. The identifier of this vulnerability is VDB-216476.
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: 6.1
Published: 2022-12-21T19:15Z
Repository: https://github.com/panicsteve/w2wiki
Language: PHP
Files changed: index.php
Commit date: 2021-01-10 12:55:43 -0800
Commit message: Add Markdown sanitization to close XSS vulnerability; credit to Markus Schneider & Marc Clement

Diff: diff --git a/index.php b/index.php
index 0737af9..c797df9 100644
--- a/index.php
+++ b/index.php
@@ -80,10 +80,28 @@ if ( REQUIRE_PASSWORD && !isset($_SESSION['password']) )
 	}
 }
 
 // Support functions
 
+function _handle_links($match)
+{
+	return "<a href=\"" . SELF . VIEW . "/" . htmlentities($match[1]) . "\">" . htmlentities($match[1]) . "</a>";
+}
+
+
+function _handle_images($match)
+{
+	return "<img src=\"" . BASE_URI . "/images/" . htmlentities($match[1]) . "\" alt=\"" . htmlentities($match[1]) . "\" />";
+}
+
+
+function _handle_message($match)
+{
+	return "[<a href=\"message:" . htmlentities($match[1]) . "\">email</a>]";
+}
+
+
 function printToolbar()
 {
 	global $upage, $page, $action;
 
 	print "<div class=\"toolbar\">";
@@ -147,13 +165,13 @@ function toHTML($inText)
 		{
 	 		$inText = preg_replace("/(?<![\>\[\/])($filename)(?!\]\>)/im", "<a href=\"" . SELF . VIEW . "/$filename\">\\1</a>", $inText);
 		}
 	}
 	
- 	$inText = preg_replace("/\[\[(.*?)\]\]/", "<a href=\"" . SELF . VIEW . "/\\1\">\\1</a>", $inText);
-	$inText = preg_replace("/\{\{(.*?)\}\}/", "<img src=\"" . BASE_URI . "/images/\\1\" alt=\"\\1\" />", $inText);
-	$inText = preg_replace("/message:(.*?)\s/", "[<a href=\"message:\\1\">email</a>]", $inText);
+	$inText = preg_replace_callback("/\[\[(.*?)\]\]/", '_handle_links', $inText);
+	$inText = preg_replace_callback("/\{\{(.*?)\}\}/", '_handle_images', $inText);
+	$inText = preg_replace_callback("/message:(.*?)\s/", '_handle_message', $inText);
 
 	$html = MarkdownExtra::defaultTransform($inText);
 	$inText = htmlentities($inText);
 
 	return $html;

Vulnerable code:  	$inText = preg_replace("/\[\[(.*?)\]\]/", "<a href=\"" . SELF . VIEW . "/\\1\">\\1</a>", $inText);
	$inText = preg_replace("/\{\{(.*?)\}\}/", "<img src=\"" . BASE_URI . "/images/\\1\" alt=\"\\1\" />", $inText);
	$inText = preg_replace("/message:(.*?)\s/", "[<a href=\"message:\\1\">email</a>]", $inText);
Fixed code: function _handle_links($match)
{
	return "<a href=\"" . SELF . VIEW . "/" . htmlentities($match[1]) . "\">" . htmlentities($match[1]) . "</a>";
}


function _handle_images($match)
{
	return "<img src=\"" . BASE_URI . "/images/" . htmlentities($match[1]) . "\" alt=\"" . htmlentities($match[1]) . "\" />";
}


function _handle_message($match)
{
	return "[<a href=\"message:" . htmlentities($match[1]) . "\">email</a>]";
}


	$inText = preg_replace_callback("/\[\[(.*?)\]\]/", '_handle_links', $inText);
	$inText = preg_replace_callback("/\{\{(.*?)\}\}/", '_handle_images', $inText);
	$inText = preg_replace_callback("/message:(.*?)\s/", '_handle_message', $inText);