CVE-2022-2470: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: Cross-site Scripting (XSS) - Reflected in GitHub repository microweber/microweber prior to 1.2.21.
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-07-22T15:15Z
Repository: https://github.com/microweber/microweber
Language: PHP
Files changed: src/MicroweberPackages/App/Http/Controllers/ApiController.php, src/MicroweberPackages/Module/ModuleManager.php
Commit date: 2022-07-18 14:08:29 +0300
Commit message: update

Diff: diff --git a/src/MicroweberPackages/App/Http/Controllers/ApiController.php b/src/MicroweberPackages/App/Http/Controllers/ApiController.php
index 2c512a5629e7..c78f7dfe9a02 100644
--- a/src/MicroweberPackages/App/Http/Controllers/ApiController.php
+++ b/src/MicroweberPackages/App/Http/Controllers/ApiController.php
@@ -65,11 +65,11 @@ class ApiController  extends FrontendController
             $this->app->content_manager->define_constants();
         }
 
 
         if (defined('TEMPLATE_DIR')) {
-             app()->template_manager->boot_template();
+            app()->template_manager->boot_template();
         }
 
         //$api_function_full = str_ireplace('api/', '', $api_function_full);
 
         $api_function_full = str_replace('..', '', $api_function_full);
@@ -914,11 +914,11 @@ class ApiController  extends FrontendController
         if ($mod_to_edit != false) {
             $mod_to_edit = str_ireplace('_mw_slash_replace_', '/', $mod_to_edit);
             $mod_iframe = true;
         }
 
-        //$data = $request_data;
+        $data = $request_data;
 
         if (($_POST)) {
             $data = $_POST;
         } else {
             $url = app()->url_manager->segment();
@@ -985,11 +985,11 @@ class ApiController  extends FrontendController
                 define('MW_MODULE_ONDROP', true);
             }
 
             unset($data['ondrop']);
         }
-        // d($data);
+
 
 
         $opts = array();
         if ($request_data) {
             $opts = $request_data;
@@ -1033,23 +1033,24 @@ class ApiController  extends FrontendController
             }
         }
 
         $has_id = false;
         if (isset($data) and is_array($data)) {
+            $data = xss_clean($data);
             foreach ($data as $k => $v) {
+                $k = $this->app->module_manager->format_attr($k);
+
                 if ($k != 'ondrop') {
                     if ($k == 'id') {
                         $has_id = true;
                     }
 
                     if (is_array($v)) {
                         $v1 = $this->app->format->array_to_base64($v);
                         $tags .= "{$k}=\"$v1\" ";
                     } else {
-                        $v = $this->app->format->clean_html($v);
-
-                        //$v = app()->database_manager->escape_string($v);
+                        $v = $this->app->module_manager->format_attr($v);
 
                         $tags .= "{$k}=\"$v\" ";
                     }
                 }
             }
@@ -1191,11 +1192,11 @@ class ApiController  extends FrontendController
                     $custom_content_data['id'] = 0;
                     $this->content_data = $custom_content_data;
                 }
 
                 $this->return_data = 1;
-                 $page = $this->frontend();
+                $page = $this->frontend();
             } else {
                 $page = $this->app->content_manager->get_by_id($_REQUEST['content_id']);
             }
         } elseif (isset($_SERVER['HTTP_REFERER'])) {
             $url = $_SERVER['HTTP_REFERER'];
diff --git a/src/MicroweberPackages/Module/ModuleManager.php b/src/MicroweberPackages/Module/ModuleManager.php
index 7781b2940704..2a3ee995fac8 100644
--- a/src/MicroweberPackages/Module/ModuleManager.php
+++ b/src/MicroweberPackages/Module/ModuleManager.php
@@ -795,10 +795,27 @@ class ModuleManager
     {
         return $this->app->parser->load($module_name, $attrs);
 
     }
 
+    public function format_attr($attr_value)
+    {
+        $attr_value = str_replace('"', '&quot;', $attr_value);
+        $attr_value = str_replace("'", '&#39;', $attr_value);
+        $attr_value = str_replace('<', '&lt;', $attr_value);
+        $attr_value = str_replace('>', '&gt;', $attr_value);
+        $attr_value = str_replace('&', '&amp;', $attr_value);
+        $attr_value = str_replace(']', '&#93;', $attr_value);
+        $attr_value = str_replace('[', '&#91;', $attr_value);
+        $attr_value = str_replace('{', '&#123;', $attr_value);
+        $attr_value = str_replace('}',  '&#125;', $attr_value);
+        $attr_value = str_replace('`',   '&#96;', $attr_value);
+        $attr_value = str_replace(';',    '&#59;', $attr_value);
+        return $attr_value;
+    }
+
+
     public function css_class($module_name)
     {
         global $mw_defined_module_classes;
 
         if (isset($mw_defined_module_classes[$module_name]) != false) {

Vulnerable code:              app()->template_manager->boot_template();
        //$data = $request_data;
        // d($data);
                        $v = $this->app->format->clean_html($v);

                        //$v = app()->database_manager->escape_string($v);
                 $page = $this->frontend();
Fixed code:             app()->template_manager->boot_template();
        $data = $request_data;

            $data = xss_clean($data);
                $k = $this->app->module_manager->format_attr($k);

                        $v = $this->app->module_manager->format_attr($v);
                $page = $this->frontend();
    public function format_attr($attr_value)
    {
        $attr_value = str_replace('"', '&quot;', $attr_value);
        $attr_value = str_replace("'", '&#39;', $attr_value);
        $attr_value = str_replace('<', '&lt;', $attr_value);
        $attr_value = str_replace('>', '&gt;', $attr_value);
        $attr_value = str_replace('&', '&amp;', $attr_value);
        $attr_value = str_replace(']', '&#93;', $attr_value);
        $attr_value = str_replace('[', '&#91;', $attr_value);
        $attr_value = str_replace('{', '&#123;', $attr_value);
        $attr_value = str_replace('}',  '&#125;', $attr_value);
        $attr_value = str_replace('`',   '&#96;', $attr_value);
        $attr_value = str_replace(';',    '&#59;', $attr_value);
        return $attr_value;
    }