CVE-2023-0786: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: Cross-site Scripting (XSS) - Generic in GitHub repository thorsten/phpmyfaq prior to 3.1.11.


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: 4.8
Published: 2023-02-12T14:15Z
Repository: https://github.com/thorsten/phpmyfaq
Language: PHP
Files changed: phpmyfaq/admin/report.view.php, phpmyfaq/src/phpMyFAQ/Report.php
Commit date: 2023-01-27 07:29:22 +0100
Commit message: fix: added missing conversion to HTML entities

Diff: diff --git a/phpmyfaq/admin/report.view.php b/phpmyfaq/admin/report.view.php
index 23c3d025c9..f0f0b9be4d 100644
--- a/phpmyfaq/admin/report.view.php
+++ b/phpmyfaq/admin/report.view.php
@@ -18,10 +18,11 @@
  * @since 2011-01-12
  */
 
 use phpMyFAQ\Filter;
 use phpMyFAQ\Report;
+use phpMyFAQ\Strings;
 
 if (!defined('IS_VALID_PHPMYFAQ')) {
     http_response_code(400);
     exit();
 }
@@ -78,16 +79,16 @@ if ($user->perm->hasPermission($user->getUserId(), 'reports')) {
         echo '<tr>';
         if ($useCategory) {
             if (0 != $data['category_parent']) {
                 printf('<td>%s</td>', $data['category_parent']);
             } else {
-                printf('<td>%s</td>', $data['category_name']);
+                printf('<td>%s</td>', Strings::htmlentities($data['category_name'] ?? ''));
             }
         }
         if ($useSubcategory) {
             if (0 != $data['category_parent']) {
-                printf('<td>%s</td>', $data['category_name']);
+                printf('<td>%s</td>', Strings::htmlentities($data['category_name']));
             } else {
                 echo '<td>n/a</td>';
             }
         }
         if ($useTranslation) {
@@ -101,20 +102,20 @@ if ($user->perm->hasPermission($user->getUserId(), 'reports')) {
         }
         if ($useSticky) {
             printf('<td>%s</td>', $data['faq_sticky']);
         }
         if ($useTitle) {
-            printf('<td>%s</td>', $data['faq_question']);
+            printf('<td>%s</td>', Strings::htmlentities($data['faq_question']));
         }
         if ($useCreationDate) {
             printf('<td>%s</td>', $data['faq_updated']);
         }
         if ($useOwner) {
-            printf('<td>%s</td>', $data['faq_org_author']);
+            printf('<td>%s</td>', Strings::htmlentities($data['faq_org_author']));
         }
         if ($useLastModified) {
-            printf('<td>%s</td>', $data['faq_last_author']);
+            printf('<td>%s</td>', Strings::htmlentities($data['faq_last_author'] ?? ''));
         }
         if ($useUrl) {
             $url = sprintf(
                 '<a href="../index.php?action=faq&amp;cat=%d&amp;id=%d&amp;artlang=%s">Link</a>',
                 $data['category_id'],
diff --git a/phpmyfaq/src/phpMyFAQ/Report.php b/phpmyfaq/src/phpMyFAQ/Report.php
index 555a123810..7b2df0823a 100644
--- a/phpmyfaq/src/phpMyFAQ/Report.php
+++ b/phpmyfaq/src/phpMyFAQ/Report.php
@@ -143,10 +143,8 @@ class Report
                 $outputString = mb_convert_encoding($outputString, 'UTF-16', $detected);
             }
         }
 
         $toBeRemoved = ['=', '+', '-', 'HYPERLINK'];
-        $outputString = str_replace($toBeRemoved, '', $outputString);
-
-        return $outputString;
+        return str_replace($toBeRemoved, '', $outputString);
     }
 }

Vulnerable code:                 printf('<td>%s</td>', $data['category_name']);
                printf('<td>%s</td>', $data['category_name']);
            printf('<td>%s</td>', $data['faq_question']);
            printf('<td>%s</td>', $data['faq_org_author']);
            printf('<td>%s</td>', $data['faq_last_author']);
        $outputString = str_replace($toBeRemoved, '', $outputString);

        return $outputString;
Fixed code: use phpMyFAQ\Strings;
                printf('<td>%s</td>', Strings::htmlentities($data['category_name'] ?? ''));
                printf('<td>%s</td>', Strings::htmlentities($data['category_name']));
            printf('<td>%s</td>', Strings::htmlentities($data['faq_question']));
            printf('<td>%s</td>', Strings::htmlentities($data['faq_org_author']));
            printf('<td>%s</td>', Strings::htmlentities($data['faq_last_author'] ?? ''));
        return str_replace($toBeRemoved, '', $outputString);