CVE-2017-5553: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: Cross-site scripting (XSS) vulnerability in plugins/markdown_plugin/_markdown.plugin.php in b2evolution before 6.8.5 allows remote authenticated users to inject arbitrary web script or HTML via a javascript: URL.
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: 2017-01-23T07:59Z
Repository: https://github.com/b2evolution/b2evolution
Language: PHP
Files changed: plugins/markdown_plugin/_parsedown.inc.php
Commit date: 2017-01-19 10:24:29 +0300
Commit message: Ignore wrong urls on markdown plugin

Diff: diff --git a/plugins/markdown_plugin/_parsedown.inc.php b/plugins/markdown_plugin/_parsedown.inc.php
index 9ab2f281d9..7aea9f0065 100644
--- a/plugins/markdown_plugin/_parsedown.inc.php
+++ b/plugins/markdown_plugin/_parsedown.inc.php
@@ -27,10 +27,11 @@ Modifications by yura:
 	    - #header {.header-class-value#header-id-value}    => <h1 id="header-id-value" class="header-class-value">header</h1>
 	    - ####header {#header-id-value.header-class-value} => <h4 class="header-class-value" id="header-id-value">header</h4>
 	9. Don't apply <p> around list and already existing paragraph tags
 	10. Don't convert HTML entities inside <code> html tags because the "Escape code" plugin does this
 	11. Fix the missed empty lines in code blocks which are started and ended with ```
+	12. Ignore wrong URLs for links and images; Allow only which begin with http://, https:// or /
 */
 
 class Parsedown
 {
 	#
@@ -98,11 +99,11 @@ class Parsedown
 		}
 		*/
 
 		# Extracts link references.
 
-		if (preg_match_all('/^[ ]{0,3}\[(.+)\][ ]?:[ ]*\n?[ ]*(.+)$/m', $text, $matches, PREG_SET_ORDER))
+		if (preg_match_all('/^[ ]{0,3}\[(.+)\][ ]?:[ ]*\n?[ ]*((https?:\/\/|\/).+)$/m', $text, $matches, PREG_SET_ORDER))
 		{
 			foreach ($matches as $matches)
 			{
 				$this->reference_map[strtolower($matches[1])] = $matches[2];
 
@@ -587,27 +588,27 @@ class Parsedown
 
 			# Inline Link / Image
 			if( strpos($text, '](') !== FALSE ) # inline
 			{
 				$text = str_replace( '&quot;', '"', $text ); // revert from html entity
-				if( preg_match_all( '/(!?)(\[((?:[^][]+|(?2))*)\])\(([^"]*?)( "([^"]+)")?\)/', $text, $matches, PREG_SET_ORDER ) )
+				if( preg_match_all( '/(!?)(\[((?:[^][]+|(?2))*)\])\((https?:\/\/|\/)([^"]*?)( "([^"]+)")?\)/', $text, $matches, PREG_SET_ORDER ) )
 				{
 					foreach ($matches as $matches)
 					{
 						if ($matches[1]) # image
 						{
 							if( $this->parse_images )
 							{ // Parse images only if it is enabled
-								$element = '<img src="'.$matches[4].'" alt="'.$matches[3].'"'.( ! empty( $matches[6] ) ? ' title="'.$matches[6].'"' : '' ).'>';
+								$element = '<img src="'.$matches[4].$matches[5].'" alt="'.$matches[3].'"'.( ! empty( $matches[7] ) ? ' title="'.$matches[7].'"' : '' ).'>';
 							}
 						}
 						else
 						{
 							if( $this->parse_links )
 							{ // Parse links only if it is enabled
 								$element_text = $this->parse_inline_elements($matches[3]);
-								$element = '<a href="'.$matches[4].'"'.( ! empty( $matches[6] ) ? ' title="'.$matches[6].'"' : '' ).'>'.$element_text.'</a>';
+								$element = '<a href="'.$matches[4].$matches[5].'"'.( ! empty( $matches[7] ) ? ' title="'.$matches[7].'"' : '' ).'>'.$element_text.'</a>';
 							}
 						}
 
 						if( ! isset( $element ) )
 						{

Vulnerable code: 		if (preg_match_all('/^[ ]{0,3}\[(.+)\][ ]?:[ ]*\n?[ ]*(.+)$/m', $text, $matches, PREG_SET_ORDER))
				if( preg_match_all( '/(!?)(\[((?:[^][]+|(?2))*)\])\(([^"]*?)( "([^"]+)")?\)/', $text, $matches, PREG_SET_ORDER ) )
								$element = '<img src="'.$matches[4].'" alt="'.$matches[3].'"'.( ! empty( $matches[6] ) ? ' title="'.$matches[6].'"' : '' ).'>';
								$element = '<a href="'.$matches[4].'"'.( ! empty( $matches[6] ) ? ' title="'.$matches[6].'"' : '' ).'>'.$element_text.'</a>';
Fixed code: 	12. Ignore wrong URLs for links and images; Allow only which begin with http://, https:// or /
		if (preg_match_all('/^[ ]{0,3}\[(.+)\][ ]?:[ ]*\n?[ ]*((https?:\/\/|\/).+)$/m', $text, $matches, PREG_SET_ORDER))
				if( preg_match_all( '/(!?)(\[((?:[^][]+|(?2))*)\])\((https?:\/\/|\/)([^"]*?)( "([^"]+)")?\)/', $text, $matches, PREG_SET_ORDER ) )
								$element = '<img src="'.$matches[4].$matches[5].'" alt="'.$matches[3].'"'.( ! empty( $matches[7] ) ? ' title="'.$matches[7].'"' : '' ).'>';
								$element = '<a href="'.$matches[4].$matches[5].'"'.( ! empty( $matches[7] ) ? ' title="'.$matches[7].'"' : '' ).'>'.$element_text.'</a>';