CVE-2017-14619: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: Cross-site scripting (XSS) vulnerability in phpMyFAQ through 2.9.8 allows remote attackers to inject arbitrary web script or HTML via the "Title of your FAQ" field in the Configuration Module.
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: 2017-09-20T21:29Z
Repository: https://github.com/thorsten/phpMyFAQ
Language: PHP
Files changed: phpmyfaq/admin/configuration.php, phpmyfaq/inc/PMF/Faq.php, phpmyfaq/index.php, phpmyfaq/main.php
Commit date: 2017-09-14 21:10:24 +0200
Commit message: Added some more protection against possible XSS attacks

Diff: diff --git a/phpmyfaq/admin/configuration.php b/phpmyfaq/admin/configuration.php
index 68e94a9bd..e376a8002 100644
--- a/phpmyfaq/admin/configuration.php
+++ b/phpmyfaq/admin/configuration.php
@@ -44,11 +44,16 @@ if ($user->perm->checkRight($user->getUserId(), 'editconfig')) {
         $oldConfigValues = $faqConfig->config;
 
         // Set the new values
         $forbiddenValues = ['{', '}', '$'];
         $newConfigValues = [];
-        $escapeValues = ['main.contactInformations', 'main.customPdfHeader', 'main.customPdfFooter'];
+        $escapeValues = [
+            'main.contactInformations',
+            'main.customPdfHeader',
+            'main.customPdfFooter',
+            'main.titleFAQ'
+        ];
 
         // Special checks
         if (isset($editData['edit']['main.enableMarkdownEditor'])) {
             $editData['edit']['main.enableWysiwygEditor'] = false; // Disable WYSIWG editor if Markdown is enabled
         }
@@ -56,11 +61,11 @@ if ($user->perm->checkRight($user->getUserId(), 'editconfig')) {
         foreach ($editData['edit'] as $key => $value) {
             // Remove forbidden characters
             $newConfigValues[$key] = str_replace($forbiddenValues, '', $value);
             // Escape some values
             if (isset($escapeValues[$key])) {
-                $newConfigValues[$key] = PMF_String::htmlspecialchars($value, ENT_HTML5);
+                $newConfigValues[$key] = PMF_String::htmlspecialchars($value, ENT_QUOTES);
             }
             $keyArray = array_values(explode('.', $key));
             $newConfigClass = array_shift($keyArray);
         }
 
diff --git a/phpmyfaq/inc/PMF/Faq.php b/phpmyfaq/inc/PMF/Faq.php
index e2e7d3b01..5a29f3cd2 100755
--- a/phpmyfaq/inc/PMF/Faq.php
+++ b/phpmyfaq/inc/PMF/Faq.php
@@ -1600,11 +1600,11 @@ class PMF_Faq
             );
         $result = $this->_config->getDb()->query($query);
 
         if ($this->_config->getDb()->numRows($result) > 0) {
             while ($row = $this->_config->getDb()->fetchObject($result)) {
-                $question = $row->question;
+                $question = PMF_String::htmlspecialchars($row->question);
             }
         } else {
             $question = $this->pmf_lang['no_cats'];
         }
 
diff --git a/phpmyfaq/index.php b/phpmyfaq/index.php
index 411f97212..5aa75d71c 100755
--- a/phpmyfaq/index.php
+++ b/phpmyfaq/index.php
@@ -477,15 +477,15 @@ if (!is_null($error)) {
 
 $faqSeo = new PMF_Seo($faqConfig);
 
 $tplMainPage = array(
     'msgLoginUser' => $user->isLoggedIn() ? $user->getUserData('display_name') : $PMF_LANG['msgLoginUser'],
-    'title' => $faqConfig->get('main.titleFAQ').$title,
+    'title' => PMF_String::htmlspecialchars($faqConfig->get('main.titleFAQ').$title),
     'baseHref' => $faqSystem->getSystemUri($faqConfig),
     'version' => $faqConfig->get('main.currentVersion'),
-    'header' => str_replace('"', '', $faqConfig->get('main.titleFAQ')),
-    'metaTitle' => str_replace('"', '', $faqConfig->get('main.titleFAQ').$title),
+    'header' => PMF_String::htmlspecialchars(str_replace('"', '', $faqConfig->get('main.titleFAQ'))),
+    'metaTitle' => PMF_String::htmlspecialchars(str_replace('"', '', $faqConfig->get('main.titleFAQ').$title)),
     'metaDescription' => $metaDescription,
     'metaKeywords' => $keywords,
     'metaPublisher' => $faqConfig->get('main.metaPublisher'),
     'metaLanguage' => $PMF_LANG['metaLanguage'],
     'metaCharset' => 'utf-8', // backwards compability
diff --git a/phpmyfaq/main.php b/phpmyfaq/main.php
index 302e2ff22..baf66c5b7 100755
--- a/phpmyfaq/main.php
+++ b/phpmyfaq/main.php
@@ -75,8 +75,8 @@ $tpl->parse(
 
 $tpl->parseBlock(
     'index',
     'breadcrumb',
     [
-        'breadcrumbHeadline' => $faqConfig->get('main.titleFAQ')
+        'breadcrumbHeadline' => PMF_String::htmlspecialchars($faqConfig->get('main.titleFAQ'))
     ]
 );
\ No newline at end of file

Vulnerable code:         $escapeValues = ['main.contactInformations', 'main.customPdfHeader', 'main.customPdfFooter'];
                $newConfigValues[$key] = PMF_String::htmlspecialchars($value, ENT_HTML5);
                $question = $row->question;
    'title' => $faqConfig->get('main.titleFAQ').$title,
    'header' => str_replace('"', '', $faqConfig->get('main.titleFAQ')),
    'metaTitle' => str_replace('"', '', $faqConfig->get('main.titleFAQ').$title),
        'breadcrumbHeadline' => $faqConfig->get('main.titleFAQ')
Fixed code:         $escapeValues = [
            'main.contactInformations',
            'main.customPdfHeader',
            'main.customPdfFooter',
            'main.titleFAQ'
        ];
                $newConfigValues[$key] = PMF_String::htmlspecialchars($value, ENT_QUOTES);
                $question = PMF_String::htmlspecialchars($row->question);
    'title' => PMF_String::htmlspecialchars($faqConfig->get('main.titleFAQ').$title),
    'header' => PMF_String::htmlspecialchars(str_replace('"', '', $faqConfig->get('main.titleFAQ'))),
    'metaTitle' => PMF_String::htmlspecialchars(str_replace('"', '', $faqConfig->get('main.titleFAQ').$title)),
        'breadcrumbHeadline' => PMF_String::htmlspecialchars($faqConfig->get('main.titleFAQ'))