CVE-2017-15734: Cross-Site Request Forgery (CSRF) (CWE-352)
value: In phpMyFAQ before 2.9.9, there is Cross-Site Request Forgery (CSRF) in admin/stat.main.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-22T18:29Z
Repository: https://github.com/thorsten/phpMyFAQ
Language: PHP
Files changed: phpmyfaq/admin/stat.main.php
Commit date: 2017-10-01 15:16:52 +0200
Commit message: Added missing CSRF protection

Diff: diff --git a/phpmyfaq/admin/stat.main.php b/phpmyfaq/admin/stat.main.php
index e22fa3462..91ed72d6e 100644
--- a/phpmyfaq/admin/stat.main.php
+++ b/phpmyfaq/admin/stat.main.php
@@ -28,11 +28,12 @@ if (!defined('IS_VALID_PHPMYFAQ')) {
         <header class="row">
             <div class="col-lg-12">
                 <h2 class="page-header">
                     <i aria-hidden="true" class="fa fa-tasks"></i> <?php echo $PMF_LANG['ad_stat_sess'] ?>
                     <div class="pull-right">
-                        <a class="btn btn-danger" href="?action=clear-visits">
+                        <a class="btn btn-danger"
+                           href="?action=clear-visits&csrf=<?php echo $user->getCsrfTokenFromSession() ?>">
                             <i aria-hidden="true" class="fa fa-trash"></i> <?php echo $PMF_LANG['ad_clear_all_visits'] ?>
                         </a>
                     </div>
                 </h2>
             </div>
@@ -45,16 +46,23 @@ if ($user->perm->checkRight($user->getUserId(), 'viewlog')) {
     $session = new PMF_Session($faqConfig);
     $date = new PMF_Date($faqConfig);
     $visits = new PMF_Visits($faqConfig);
     $statdelete = PMF_Filter::filterInput(INPUT_POST, 'statdelete', FILTER_SANITIZE_STRING);
     $month = PMF_Filter::filterInput(INPUT_POST, 'month', FILTER_SANITIZE_STRING);
-    $csrfToken = PMF_Filter::filterInput(INPUT_POST, 'csrf', FILTER_SANITIZE_STRING);
+    $csrfTokenFromPost = PMF_Filter::filterInput(INPUT_POST, 'csrf', FILTER_SANITIZE_STRING);
+    $csrfTokenFromGet = PMF_Filter::filterInput(INPUT_GET, 'csrf', FILTER_SANITIZE_STRING);
 
-    if (!isset($_SESSION['phpmyfaq_csrf_token']) || $_SESSION['phpmyfaq_csrf_token'] !== $csrfToken) {
+    if (!isset($_SESSION['phpmyfaq_csrf_token']) || $_SESSION['phpmyfaq_csrf_token'] !== $csrfTokenFromPost) {
         $statdelete = null;
     }
 
+    if (!isset($_SESSION['phpmyfaq_csrf_token']) || $_SESSION['phpmyfaq_csrf_token'] !== $csrfTokenFromGet) {
+        $clearVisits = false;
+    } else {
+        $clearVisits = true;
+    }
+
     // Delete sessions and session files
     if (!is_null($statdelete) && !is_null($month)) {
         $dir = opendir(PMF_ROOT_DIR.'/data');
         $first = 9999999999999999999999999;
         $last = 0;
@@ -78,11 +86,11 @@ if ($user->perm->checkRight($user->getUserId(), 'viewlog')) {
 
         printf('<p class="alert alert-success">%s</p>', $PMF_LANG['ad_adminlog_delete_success']);
     }
 
     // Reset all visits and sessions
-    if ('clear-visits' === $action) {
+    if ('clear-visits' === $action && $clearVisits) {
 
         // Clear visits
         $visits->resetAll();
 
         // Delete logifles

Vulnerable code:                         <a class="btn btn-danger" href="?action=clear-visits">
    $csrfToken = PMF_Filter::filterInput(INPUT_POST, 'csrf', FILTER_SANITIZE_STRING);
    if (!isset($_SESSION['phpmyfaq_csrf_token']) || $_SESSION['phpmyfaq_csrf_token'] !== $csrfToken) {
    if ('clear-visits' === $action) {
Fixed code:                         <a class="btn btn-danger"
                           href="?action=clear-visits&csrf=<?php echo $user->getCsrfTokenFromSession() ?>">
    $csrfTokenFromPost = PMF_Filter::filterInput(INPUT_POST, 'csrf', FILTER_SANITIZE_STRING);
    $csrfTokenFromGet = PMF_Filter::filterInput(INPUT_GET, 'csrf', FILTER_SANITIZE_STRING);
    if (!isset($_SESSION['phpmyfaq_csrf_token']) || $_SESSION['phpmyfaq_csrf_token'] !== $csrfTokenFromPost) {
    if (!isset($_SESSION['phpmyfaq_csrf_token']) || $_SESSION['phpmyfaq_csrf_token'] !== $csrfTokenFromGet) {
        $clearVisits = false;
    } else {
        $clearVisits = true;
    }

    if ('clear-visits' === $action && $clearVisits) {