CVE-2021-29436: Cross-Site Request Forgery (CSRF) (CWE-352)
value: Anuko Time Tracker is an open source, web-based time tracking application written in PHP. In Time Tracker before version 1.19.27.5431 a Cross site request forgery (CSRF) vulnerability existed. The nature of CSRF is that a logged on user may be tricked by social engineering to click on an attacker-provided form that executes an unintended action such as changing user password. The vulnerability is fixed in Time Tracker version 1.19.27.5431. Upgrade is recommended. If upgrade is not practical, introduce ttMitigateCSRF() function in /WEB-INF/lib/common.php.lib using the latest available code and call it from ttAccessAllowed().
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.1
Published: 2021-04-13T20:15Z
Repository: https://github.com/anuko/timetracker
Language: PHP
Files changed: WEB-INF/config.php.dist, WEB-INF/lib/common.lib.php, initialize.php
Commit date: 2021-04-12 17:14:41 +0000
Commit message: Tested CSRF fix for custom ports - it's working, also removed unnecessary logging.

Diff: diff --git a/WEB-INF/config.php.dist b/WEB-INF/config.php.dist
index 1b7b32b0a..3787cbc94 100644
--- a/WEB-INF/config.php.dist
+++ b/WEB-INF/config.php.dist
@@ -163,11 +163,11 @@ define('AUTH_MODULE', 'db');
 // define('DEBUG', false); // Note: enabling DEBUG breaks redirects as debug output is printed before setting redirect header. Do not enable on production systems.
 
 
 // HTTP_TARGET - defines http target for cross site request forgery protection.
 // It can be used when you access the application via a proxy.
-// define('HTTP_TARGET', 'localhost');
+// define('HTTP_TARGET', 'localhost:8080');
 
 
 // Group managers can set monthly work hour quota for years between the following  values.
 // define('MONTHLY_QUOTA_YEAR_START', 2010); // If nothing is specified, it falls back to 2015.
 // define('MONTHLY_QUOTA_YEAR_END', 2025);   // If nothing is specified, it falls back to 2030.
diff --git a/WEB-INF/lib/common.lib.php b/WEB-INF/lib/common.lib.php
index 52589c6e0..d5b43f57f 100644
--- a/WEB-INF/lib/common.lib.php
+++ b/WEB-INF/lib/common.lib.php
@@ -412,19 +412,16 @@ function ttMitigateCSRF() {
       $origin = substr($origin, $pos+2); // Strip protocol.
       $pos = strpos($origin, '/');
       $origin = substr($origin, 0, $pos); // Leave host only.
     }
   }
-  error_log("origin: ".$origin);
   $target = defined('HTTP_TARGET') ? HTTP_TARGET : $_SERVER['HTTP_HOST'];
-  error_log("target: ".$target);
   if (strcmp($origin, $target)) {
     error_log("Potential cross site request forgery. Origin: '$origin' does not match target: '$target'.");
-    return false; // Origin and target do not match,
+    return false; // Origin and target do not match.
   }
 
-  // TODO: review and improve this function for custom ports.
   return true;
 }
 
 
 // ttStartsWith functions checks if a string starts with a given substring.
diff --git a/initialize.php b/initialize.php
index aadc0bb07..e8588857f 100644
--- a/initialize.php
+++ b/initialize.php
@@ -11,11 +11,11 @@ error_reporting(E_ALL & ~E_NOTICE & ~E_STRICT); // & ~E_DEPRECATED);
 
 // Disable displaying errors on screen.
 ini_set('display_errors', 'Off');
 
 // require_once('init_auth.php');
-define("APP_VERSION", "1.19.27.5431");
+define("APP_VERSION", "1.19.27.5432");
 define("APP_DIR", dirname(__FILE__));
 define("LIBRARY_DIR", APP_DIR."/WEB-INF/lib");
 define("TEMPLATE_DIR", APP_DIR."/WEB-INF/templates");
 // Date format for database and URI parameters.
 define('DB_DATEFORMAT', '%Y-%m-%d');

Vulnerable code: // define('HTTP_TARGET', 'localhost');
  error_log("origin: ".$origin);
  error_log("target: ".$target);
    return false; // Origin and target do not match,
  // TODO: review and improve this function for custom ports.
define("APP_VERSION", "1.19.27.5431");
Fixed code: // define('HTTP_TARGET', 'localhost:8080');
    return false; // Origin and target do not match.
define("APP_VERSION", "1.19.27.5432");