CVE-2017-15808: Cross-Site Request Forgery (CSRF) (CWE-352)
value: In phpMyFaq before 2.9.9, there is CSRF in admin/ajax.config.php.
CWE description: The web application does not, or can not, sufficiently verify whether a well-formed, valid, consistent request was intentionally provided by the user who submitted the request.
CVSS v3 base score: 8.8
Published: 2017-10-23T17:29Z
Repository: https://github.com/thorsten/phpMyFAQ
Language: PHP
Files changed: phpmyfaq/admin/ajax.config.php, phpmyfaq/admin/instances.php
Commit date: 2017-10-10 19:29:05 +0200
Commit message: Added missing CSRF token

Diff: diff --git a/phpmyfaq/admin/ajax.config.php b/phpmyfaq/admin/ajax.config.php
index 99843004f7..e979b928a1 100644
--- a/phpmyfaq/admin/ajax.config.php
+++ b/phpmyfaq/admin/ajax.config.php
@@ -36,10 +36,15 @@ $stopwords = new PMF_Stopwords($faqConfig);
 
 switch ($ajaxAction) {
 
     case 'add_instance':
 
+        if (!isset($_SESSION['phpmyfaq_csrf_token']) || $_SESSION['phpmyfaq_csrf_token'] !== $csrfToken) {
+            $http->sendJsonWithHeaders(array('error' => $PMF_LANG['err_NotAuth']));
+            exit(1);
+        }
+
         $url = PMF_Filter::filterInput(INPUT_GET, 'url', FILTER_SANITIZE_STRING);
         $instance = PMF_Filter::filterInput(INPUT_GET, 'instance', FILTER_SANITIZE_STRING);
         $comment = PMF_Filter::filterInput(INPUT_GET, 'comment', FILTER_SANITIZE_STRING);
         $email = PMF_Filter::filterInput(INPUT_GET, 'email', FILTER_VALIDATE_EMAIL);
         $admin = PMF_Filter::filterInput(INPUT_GET, 'admin', FILTER_SANITIZE_STRING);
diff --git a/phpmyfaq/admin/instances.php b/phpmyfaq/admin/instances.php
index 2b0552972a..c9abddbc1c 100644
--- a/phpmyfaq/admin/instances.php
+++ b/phpmyfaq/admin/instances.php
@@ -95,13 +95,13 @@ if ($user->perm->checkRight($user->getUserId(), 'editinstances')) {
         </thead>
         <tbody>
         <?php
         foreach ($instance->getAllInstances() as $site):
             $currentInstance = new PMF_Instance($faqConfig);
-    $currentInstance->getInstanceById($site->id);
-    $currentInstance->setId($site->id);
-    ?>
+            $currentInstance->getInstanceById($site->id);
+            $currentInstance->setId($site->id);
+            ?>
         <tr id="row-instance-<?php print $site->id ?>">
             <td><?php print $site->id ?></td>
             <td><a href="<?php print $site->url.$site->instance ?>"><?php print $site->url ?></a></td>
             <td><?php print $site->instance ?></td>
             <td><?php print $site->comment ?></td>
@@ -115,16 +115,14 @@ if ($user->perm->checkRight($user->getUserId(), 'editinstances')) {
                 <a href="javascript:;" id="delete-instance-<?php print $site->id ?>"
                    class="btn btn-danger pmf-instance-delete"
                    data-csrf-token="<?php echo $user->getCsrfTokenFromSession() ?>">
                     <i aria-hidden="true" class="fa fa-trash"></i>
                 </a>
-                <?php endif;
-    ?>
+                <?php endif; ?>
             </td>
         </tr>
-        <?php endforeach;
-    ?>
+        <?php endforeach; ?>
         </tbody>
     </table>
 
     <div class="modal fade" id="pmf-modal-add-instance">
         <div class="modal-dialog">
@@ -133,10 +131,11 @@ if ($user->perm->checkRight($user->getUserId(), 'editinstances')) {
                     <a class="close" data-dismiss="modal">×</a>
                     <h3><?php echo $PMF_LANG['ad_instance_add'] ?></h3>
                 </div>
                 <div class="modal-body">
                     <form class="form-horizontal" action="#" method="post" accept-charset="utf-8">
+                        <input type="hidden" name="csrf" id="csrf" value="<?php echo $user->getCsrfTokenFromSession() ?>">
                         <div class="form-group">
                             <label class="control-label col-lg-4">
                                 <?php echo $PMF_LANG['ad_instance_url'] ?>:
                             </label>
                             <div class="col-lg-8">
@@ -203,20 +202,22 @@ if ($user->perm->checkRight($user->getUserId(), 'editinstances')) {
         (function() {
 
             // Add instance
             $('.pmf-instance-add').click(function(event) {
                 event.preventDefault();
+                var csrf     = $('#csrf').val();
                 var url      = $('#url').val();
                 var instance = $('#instance').val();
                 var comment  = $('#comment').val();
                 var email    = $('#email').val();
                 var admin    = $('#admin').val();
                 var password = $('#password').val();
 
                 $.get('index.php',
-                    { action: 'ajax', ajax: 'config', ajaxaction: 'add_instance',
-                        url: url, instance: instance, comment: comment, email: email, admin: admin, password: password
+                    {
+                        action: 'ajax', ajax: 'config', ajaxaction: 'add_instance', csrf: csrf, url: url,
+                        instance: instance, comment: comment, email: email, admin: admin, password: password
                     },
                     function(data) {
                         if (typeof(data.added) === 'undefined') {
                             $('.table').after(
                                 '<div class="alert alert-danger">Could not add instance</div>'

Vulnerable code:     $currentInstance->getInstanceById($site->id);
    $currentInstance->setId($site->id);
    ?>
                <?php endif;
    ?>
        <?php endforeach;
    ?>
                    { action: 'ajax', ajax: 'config', ajaxaction: 'add_instance',
                        url: url, instance: instance, comment: comment, email: email, admin: admin, password: password
Fixed code:         if (!isset($_SESSION['phpmyfaq_csrf_token']) || $_SESSION['phpmyfaq_csrf_token'] !== $csrfToken) {
            $http->sendJsonWithHeaders(array('error' => $PMF_LANG['err_NotAuth']));
            exit(1);
        }

            $currentInstance->getInstanceById($site->id);
            $currentInstance->setId($site->id);
            ?>
                <?php endif; ?>
        <?php endforeach; ?>
                        <input type="hidden" name="csrf" id="csrf" value="<?php echo $user->getCsrfTokenFromSession() ?>">
                var csrf     = $('#csrf').val();
                    {
                        action: 'ajax', ajax: 'config', ajaxaction: 'add_instance', csrf: csrf, url: url,
                        instance: instance, comment: comment, email: email, admin: admin, password: password