Vulnerability: In phpMyFAQ before 2.9.9, there is Cross-Site Request Forgery (CSRF) in admin/news.php.
Vulnerability ID: CVE-2017-15732
CWE: CWE-352
Severity score: 6.4
Project: https://github.com/thorsten/phpMyFAQ
Published: 2017-10-22
File: phpmyfaq/admin/news.php
Commit message: Added missing CSRF check
Commit author: Thorsten Rinne

Vulnerable version (before fix):
  $news = new PMF_News($faqConfig);  if ('addnews' == $action && $user->perm->checkRight($user->getUserId(), 'addnews')) {     ?>         <header class="row">             <div class="col-lg-12">                 <h2 class="page-header"><i aria-hidden="true" class="fa fa-pencil"></i> <?php echo $PMF_LANG['ad_news_add'];     ?></h2>             </div>         </header>                       <div class="form-group">                         <label class="col-lg-2 control-label" for="newsheader">                             <?php echo $PMF_LANG['ad_news_header'];     ?>                         </label>                         <div class="col-lg-4">                             <input class="form-control" type="text" name="newsheader">                         </div>                     </div>                      <div class="form-group">                         <label class="col-lg-2 control-label" for="news"><?php echo $PMF_LANG['ad_news_text'];     ?>:</label>                         <div class="col-lg-4">                             <noscript>Please enable JavaScript to use the WYSIWYG editor!</noscript>                             <textarea name="news" rows="5" class="form-control"></textarea>                         </div>                     </div>                      <div class="form-group">                         <label class="col-lg-2 control-label" for="authorName"><?php echo $PMF_LANG['ad_news_author_name'];     ?></label>                         <div class="col-lg-4">                             <input class="form-control" type="text" name="authorName" id="authorName"                                    value="<?php echo $user->getUserData('display_name');     ?>"/>                         </div>                     </div>                      <div class="form-group">                         <label class="col-lg-2 control-label" for="authorEmail"><?php echo $PMF_LANG['ad_news_author_email'];     ?></label>                         <div class="col-lg-4">                             <input class="form-control" type="email" name="authorEmail" id="authorEmail"                                    value="<?php echo $user->getUserData('email');     ?>"/>                         </div>                     </div>                      <div class="form-group">                         <label class="col-lg-2 control-label" for="active">                             <?php echo $PMF_LANG['ad_news_set_active'];     ?>:                         </label>                         <div class="col-lg-4 checkbox">                             <label>                                 <input type="checkbox" name="active" id="active" value="y">                                 <?php echo $PMF_LANG['ad_gen_yes'];     ?>                             </label>                         </div>                     </div>                      <div class="form-group">                         <label class="col-lg-2 control-label" for="comment"><?php echo $PMF_LANG['ad_news_allowComments'];     ?></label>                         <div class="col-lg-4 checkbox">                             <label>                                 <input type="checkbox" name="comment" id="comment" value="y">                                 <?php echo $PMF_LANG['ad_gen_yes'];     ?>                             </label>                         </div>                     </div>                      <div class="form-group">                         <label class="col-lg-2 control-label" for="link"><?php echo $PMF_LANG['ad_news_link_url'];     ?></label>                         <div class="col-lg-4">                             <input class="form-control" type="url" name="link" id="link" placeholder="http://www.example.com/">                         </div>                     </div>                      <div class="form-group">                         <label class="col-lg-2 control-label" for="linkTitle"><?php echo $PMF_LANG['ad_news_link_title'];     ?></label>                         <div class="col-lg-4">                             <input type="text" name="linkTitle" id="linkTitle" class="form-control">                         </div>                     </div>                      <div class="form-group">                         <label class="col-lg-2 control-label" ><?php echo $PMF_LANG['ad_news_link_target'];     ?></label>                         <div class="col-lg-4 radio">                             <label>                                 <input type="radio" name="target" value="blank">                         </div>                     </div>                     <div class="form-group">                         <label class="col-lg-2 control-label" for="langTo"><?php echo $PMF_LANG['ad_entry_locale'];     ?>:</label>                         <div class="col-lg-4">                             <?php echo PMF_Language::selectLanguages($LANGCODE, false, [], 'langTo');     ?>                         </div>                     </div>                      <legend><?php echo $PMF_LANG['ad_news_expiration_window'];     ?></legend>                     <div class="form-group">                         <label class="col-lg-2 control-label" for="dateStart"><?php echo $PMF_LANG['ad_news_from'];     ?></label>             <div class="col-lg-12"> <?php     $precheck = PMF_Filter::filterInput(INPUT_POST, 'really', FILTER_SANITIZE_STRING, 'no');     $delete_id = PMF_Filter::filterInput(INPUT_GET, 'id', FILTER_VALIDATE_INT);      if ('no' == $precheck) {         ?>     <div class="form-group"><?php echo $PMF_LANG['ad_news_del'];         ?></div>     <div class="text-center">     <form action="?action=deletenews" method="post" accept-charset="utf-8">     <input type="hidden" name="id" value="<?php echo $delete_id;         ?>">     <input type="hidden" name="really" value="yes">         <button class="btn btn-warning" type="submit" name="submit">             <?php echo $PMF_LANG['ad_news_yesdelete']; <?php      } else {         $delete_id = PMF_Filter::filterInput(INPUT_POST, 'id', FILTER_VALIDATE_INT);         $news->deleteNews($delete_id);         printf('<p class="alert alert-success">%s</p>', $PMF_LANG['ad_news_delsuc']);         printf('<div class="form-group">&rarr; <a href="?action=news">%s</a></p>', $PMF_LANG['msgNews']);     } } else {     echo $PMF_LANG['err_NotAuth'];

Fixed version (after fix):
  $news = new PMF_News($faqConfig);  $csrfToken = PMF_Filter::filterInput(INPUT_POST, 'csrf', FILTER_SANITIZE_STRING); if (!isset($_SESSION['phpmyfaq_csrf_token']) || $_SESSION['phpmyfaq_csrf_token'] !== $csrfToken) {     $csrfCheck = false; } else {     $csrfCheck = true; }  if ('addnews' == $action && $user->perm->checkRight($user->getUserId(), 'addnews')) {     ?>         <header class="row">             <div class="col-lg-12">                 <h2 class="page-header"><i aria-hidden="true" class="fa fa-pencil"></i> <?php echo $PMF_LANG['ad_news_add'] ?></h2>             </div>         </header>                       <div class="form-group">                         <label class="col-lg-2 control-label" for="newsheader">                             <?php echo $PMF_LANG['ad_news_header'] ?>                         </label>                         <div class="col-lg-4">                             <input class="form-control" type="text" name="newsheader">                         </div>                     </div>                      <div class="form-group">                         <label class="col-lg-2 control-label" for="news"><?php echo $PMF_LANG['ad_news_text'] ?>:</label>                         <div class="col-lg-4">                             <noscript>Please enable JavaScript to use the WYSIWYG editor!</noscript>                             <textarea name="news" rows="5" class="form-control"></textarea>                         </div>                     </div>                      <div class="form-group">                         <label class="col-lg-2 control-label" for="authorName"><?php echo $PMF_LANG['ad_news_author_name'] ?></label>                         <div class="col-lg-4">                             <input class="form-control" type="text" name="authorName" id="authorName"                                    value="<?php echo $user->getUserData('display_name') ?>">                         </div>                     </div>                      <div class="form-group">                         <label class="col-lg-2 control-label" for="authorEmail"><?php echo $PMF_LANG['ad_news_author_email'] ?></label>                         <div class="col-lg-4">                             <input class="form-control" type="email" name="authorEmail" id="authorEmail"                                    value="<?php echo $user->getUserData('email') ?>">                         </div>                     </div>                      <div class="form-group">                         <label class="col-lg-2 control-label" for="active">                             <?php echo $PMF_LANG['ad_news_set_active'] ?>:                         </label>                         <div class="col-lg-4 checkbox">                             <label>                                 <input type="checkbox" name="active" id="active" value="y">                                 <?php echo $PMF_LANG['ad_gen_yes'] ?>                             </label>                         </div>                     </div>                      <div class="form-group">                         <label class="col-lg-2 control-label" for="comment"><?php echo $PMF_LANG['ad_news_allowComments'] ?></label>                         <div class="col-lg-4 checkbox">                             <label>                                 <input type="checkbox" name="comment" id="comment" value="y">                                 <?php echo $PMF_LANG['ad_gen_yes'] ?>                             </label>                         </div>                     </div>                      <div class="form-group">                         <label class="col-lg-2 control-label" for="link"><?php echo $PMF_LANG['ad_news_link_url'] ?></label>                         <div class="col-lg-4">                             <input class="form-control" type="url" name="link" id="link" placeholder="http://www.example.com/">                         </div>                     </div>                      <div class="form-group">                         <label class="col-lg-2 control-label" for="linkTitle"><?php echo $PMF_LANG['ad_news_link_title'] ?></label>                         <div class="col-lg-4">                             <input type="text" name="linkTitle" id="linkTitle" class="form-control">                         </div>                     </div>                      <div class="form-group">                         <label class="col-lg-2 control-label" ><?php echo $PMF_LANG['ad_news_link_target'] ?></label>                         <div class="col-lg-4 radio">                             <label>                                 <input type="radio" name="target" value="blank">                         </div>                     </div>                     <div class="form-group">                         <label class="col-lg-2 control-label" for="langTo"><?php echo $PMF_LANG['ad_entry_locale'] ?>:</label>                         <div class="col-lg-4">                             <?php echo PMF_Language::selectLanguages($LANGCODE, false, [], 'langTo') ?>                         </div>                     </div>                      <legend><?php echo $PMF_LANG['ad_news_expiration_window'] ?></legend>                     <div class="form-group">                         <label class="col-lg-2 control-label" for="dateStart"><?php echo $PMF_LANG['ad_news_from'];     ?></label>             <div class="col-lg-12"> <?php     $precheck = PMF_Filter::filterInput(INPUT_POST, 'really', FILTER_SANITIZE_STRING, 'no');     $deleteId = PMF_Filter::filterInput(INPUT_GET, 'id', FILTER_VALIDATE_INT);      if ('no' == $precheck) {         ?>     <div class="form-group"><?php echo $PMF_LANG['ad_news_del'];         ?></div>     <div class="text-center">     <form action="?action=deletenews" method="post" accept-charset="utf-8">     <input type="hidden" name="id" value="<?php echo $deleteId ?>">     <input type="hidden" name="csrf" value="<?php echo $user->getCsrfTokenFromSession() ?>">     <input type="hidden" name="really" value="yes">         <button class="btn btn-warning" type="submit" name="submit">             <?php echo $PMF_LANG['ad_news_yesdelete']; <?php      } else {         if ($csrfCheck) {             $deleteId = PMF_Filter::filterInput(INPUT_POST, 'id', FILTER_VALIDATE_INT);             $news->deleteNews($deleteId);             printf('<p class="alert alert-success">%s</p>', $PMF_LANG['ad_news_delsuc']);             printf('<div class="form-group">&rarr; <a href="?action=news">%s</a></p>', $PMF_LANG['msgNews']);         }     } } else {     echo $PMF_LANG['err_NotAuth'];

Patch:
patch: @@ -29,12 +29,18 @@
 
 $news = new PMF_News($faqConfig);
 
+$csrfToken = PMF_Filter::filterInput(INPUT_POST, 'csrf', FILTER_SANITIZE_STRING);
+if (!isset($_SESSION['phpmyfaq_csrf_token']) || $_SESSION['phpmyfaq_csrf_token'] !== $csrfToken) {
+    $csrfCheck = false;
+} else {
+    $csrfCheck = true;
+}
+
 if ('addnews' == $action && $user->perm->checkRight($user->getUserId(), 'addnews')) {
     ?>
         <header class="row">
             <div class="col-lg-12">
-                <h2 class="page-header"><i aria-hidden="true" class="fa fa-pencil"></i> <?php echo $PMF_LANG['ad_news_add'];
-    ?></h2>
+                <h2 class="page-header"><i aria-hidden="true" class="fa fa-pencil"></i> <?php echo $PMF_LANG['ad_news_add'] ?></h2>
             </div>
         </header>
 
@@ -44,88 +50,75 @@
 
                     <div class="form-group">
                         <label class="col-lg-2 control-label" for="newsheader">
-                            <?php echo $PMF_LANG['ad_news_header'];
-    ?>
+                            <?php echo $PMF_LANG['ad_news_header'] ?>
                         </label>
                         <div class="col-lg-4">
                             <input class="form-control" type="text" name="newsheader">
                         </div>
                     </div>
 
                     <div class="form-group">
-                        <label class="col-lg-2 control-label" for="news"><?php echo $PMF_LANG['ad_news_text'];
-    ?>:</label>
+                        <label class="col-lg-2 control-label" for="news"><?php echo $PMF_LANG['ad_news_text'] ?>:</label>
                         <div class="col-lg-4">
                             <noscript>Please enable JavaScript to use the WYSIWYG editor!</noscript>
                             <textarea name="news" rows="5" class="form-control"></textarea>
                         </div>
                     </div>
 
                     <div class="form-group">
-                        <label class="col-lg-2 control-label" for="authorName"><?php echo $PMF_LANG['ad_news_author_name'];
-    ?></label>
+                        <label class="col-lg-2 control-label" for="authorName"><?php echo $PMF_LANG['ad_news_author_name'] ?></label>
                         <div class="col-lg-4">
                             <input class="form-control" type="text" name="authorName" id="authorName"
-                                   value="<?php echo $user->getUserData('display_name');
-    ?>"/>
+                                   value="<?php echo $user->getUserData('display_name') ?>">
                         </div>
                     </div>
 
                     <div class="form-group">
-                        <label class="col-lg-2 control-label" for="authorEmail"><?php echo $PMF_LANG['ad_news_author_email'];
-    ?></label>
+                        <label class="col-lg-2 control-label" for="authorEmail"><?php echo $PMF_LANG['ad_news_author_email'] ?></label>
                         <div class="col-lg-4">
                             <input class="form-control" type="email" name="authorEmail" id="authorEmail"
-                                   value="<?php echo $user->getUserData('email');
-    ?>"/>
+                                   value="<?php echo $user->getUserData('email') ?>">
                         </div>
                     </div>
 
                     <div class="form-group">
                         <label class="col-lg-2 control-label" for="active">
-                            <?php echo $PMF_LANG['ad_news_set_active'];
-    ?>:
+                            <?php echo $PMF_LANG['ad_news_set_active'] ?>:
                         </label>
                         <div class="col-lg-4 checkbox">
                             <label>
                                 <input type="checkbox" name="active" id="active" value="y">
-                                <?php echo $PMF_LANG['ad_gen_yes'];
-    ?>
+                                <?php echo $PMF_LANG['ad_gen_yes'] ?>
                             </label>
                         </div>
                     </div>
 
                     <div class="form-group">
-                        <label class="col-lg-2 control-label" for="comment"><?php echo $PMF_LANG['ad_news_allowComments'];
-    ?></label>
+                        <label class="col-lg-2 control-label" for="comment"><?php echo $PMF_LANG['ad_news_allowComments'] ?></label>
                         <div class="col-lg-4 checkbox">
                             <label>
                                 <input type="checkbox" name="comment" id="comment" value="y">
-                                <?php echo $PMF_LANG['ad_gen_yes'];
-    ?>
+                                <?php echo $PMF_LANG['ad_gen_yes'] ?>
                             </label>
                         </div>
                     </div>
 
                     <div class="form-group">
-                        <label class="col-lg-2 control-label" for="link"><?php echo $PMF_LANG['ad_news_link_url'];
-    ?></label>
+                        <label class="col-lg-2 control-label" for="link"><?php echo $PMF_LANG['ad_news_link_url'] ?></label>
                         <div class="col-lg-4">
                             <input class="form-control" type="url" name="link" id="link" placeholder="http://www.example.com/">
                         </div>
                     </div>
 
                     <div class="form-group">
-                        <label class="col-lg-2 control-label" for="linkTitle"><?php echo $PMF_LANG['ad_news_link_title'];
-    ?></label>
+                        <label class="col-lg-2 control-label" for="linkTitle"><?php echo $PMF_LANG['ad_news_link_title'] ?></label>
                         <div class="col-lg-4">
                             <input type="text" name="linkTitle" id="linkTitle" class="form-control">
                         </div>
                     </div>
 
                     <div class="form-group">
-                        <label class="col-lg-2 control-label" ><?php echo $PMF_LANG['ad_news_link_target'];
-    ?></label>
+                        <label class="col-lg-2 control-label" ><?php echo $PMF_LANG['ad_news_link_target'] ?></label>
                         <div class="col-lg-4 radio">
                             <label>
                                 <input type="radio" name="target" value="blank">
@@ -140,16 +133,13 @@
                         </div>
                     </div>
                     <div class="form-group">
-                        <label class="col-lg-2 control-label" for="langTo"><?php echo $PMF_LANG['ad_entry_locale'];
-    ?>:</label>
+                        <label class="col-lg-2 control-label" for="langTo"><?php echo $PMF_LANG['ad_entry_locale'] ?>:</label>
                         <div class="col-lg-4">
-                            <?php echo PMF_Language::selectLanguages($LANGCODE, false, [], 'langTo');
-    ?>
+                            <?php echo PMF_Language::selectLanguages($LANGCODE, false, [], 'langTo') ?>
                         </div>
                     </div>
 
-                    <legend><?php echo $PMF_LANG['ad_news_expiration_window'];
-    ?></legend>
+                    <legend><?php echo $PMF_LANG['ad_news_expiration_window'] ?></legend>
                     <div class="form-group">
                         <label class="col-lg-2 control-label" for="dateStart"><?php echo $PMF_LANG['ad_news_from'];
     ?></label>
@@ -594,16 +584,16 @@
             <div class="col-lg-12">
 <?php
     $precheck = PMF_Filter::filterInput(INPUT_POST, 'really', FILTER_SANITIZE_STRING, 'no');
-    $delete_id = PMF_Filter::filterInput(INPUT_GET, 'id', FILTER_VALIDATE_INT);
+    $deleteId = PMF_Filter::filterInput(INPUT_GET, 'id', FILTER_VALIDATE_INT);
 
     if ('no' == $precheck) {
         ?>
     <div class="form-group"><?php echo $PMF_LANG['ad_news_del'];
         ?></div>
     <div class="text-center">
     <form action="?action=deletenews" method="post" accept-charset="utf-8">
-    <input type="hidden" name="id" value="<?php echo $delete_id;
-        ?>">
+    <input type="hidden" name="id" value="<?php echo $deleteId ?>">
+    <input type="hidden" name="csrf" value="<?php echo $user->getCsrfTokenFromSession() ?>">
     <input type="hidden" name="really" value="yes">
         <button class="btn btn-warning" type="submit" name="submit">
             <?php echo $PMF_LANG['ad_news_yesdelete'];
@@ -626,10 +616,12 @@
 <?php
 
     } else {
-        $delete_id = PMF_Filter::filterInput(INPUT_POST, 'id', FILTER_VALIDATE_INT);
-        $news->deleteNews($delete_id);
-        printf('<p class="alert alert-success">%s</p>', $PMF_LANG['ad_news_delsuc']);
-        printf('<div class="form-group">&rarr; <a href="?action=news">%s</a></p>', $PMF_LANG['msgNews']);
+        if ($csrfCheck) {
+            $deleteId = PMF_Filter::filterInput(INPUT_POST, 'id', FILTER_VALIDATE_INT);
+            $news->deleteNews($deleteId);
+            printf('<p class="alert alert-success">%s</p>', $PMF_LANG['ad_news_delsuc']);
+            printf('<div class="form-group">&rarr; <a href="?action=news">%s</a></p>', $PMF_LANG['msgNews']);
+        }
     }
 } else {
     echo $PMF_LANG['err_NotAuth'];
path: phpmyfaq/admin/news.php