CVE-2020-15255 (PHP, published 2020-10-16T17:15Z)
Description: value: In Anuko Time Tracker before verion 1.19.23.5325, due to not properly filtered user input a CSV export of a report could contain cells that are treated as formulas by spreadsheet software (for example, when a cell value starts with an equal sign). This is fixed in version 1.19.23.5325.
Severity: MEDIUM (CVSS v3 base score: 7.3)
Weakness: CWE-1236 \u2014 Improper Neutralization of Formula Elements in a CSV File
The product saves user-provided information into a Comma-Separated Value (CSV) file, but it does not neutralize or incorrectly neutralizes special elements that could be interpreted as a command when the file is opened by a spreadsheet product.
Repository: https://github.com/anuko/timetracker
Files changed:
WEB-INF/lib/common.lib.php
initialize.php
tofile.php
Commit message: Security fix for csv injections.


Vulnerable code:
define("APP_VERSION", "1.19.23.5324");
        if ($bean->getAttribute($checkbox_control_name)) print ',"'.str_replace('"','""',$userField['label']).'"';
        if ($bean->getAttribute($checkbox_control_name)) print ',"'.str_replace('"','""',$timeField['label']).'"';
      if ($user->can('view_reports') || $user->can('view_all_reports') || $user->isClient()) print ',"'.str_replace('"','""',$item['user']).'"';
          if ($bean->getAttribute($checkbox_control_name)) print ',"'.str_replace('"','""',$item[$field_name]).'"';
      if ($bean->getAttribute('chclient')) print ',"'.str_replace('"','""',$item['client']).'"';
      if ($bean->getAttribute('chproject')) print ',"'.str_replace('"','""',$item['project']).'"';
      if ($bean->getAttribute('chtask')) print ',"'.str_replace('"','""',$item['task']).'"';
          if ($bean->getAttribute($checkbox_control_name)) print ',"'.str_replace('"','""',$item[$field_name]).'"';
      if ($bean->getAttribute('chnote')) print ',"'.str_replace('"','""',$item['note']).'"';
      if ($bean->getAttribute('chinvoice')) print ',"'.str_replace('"','""',$item['invoice']).'"';
      if ($bean->getAttribute('chtimesheet')) print ',"'.str_replace('"','""',$item['timesheet_name']).'"';

Fixed code:

// ttNeutralizeForCsv neutralizes user input for export to CSV files
// by removing =, +, -, and @ characters from the beginning of cell values.
// This mitigates a risk of CSV injection, see https://owasp.org/www-community/attacks/CSV_Injection
// Additionally, it replaces each quote character with a double quote.
function ttNeutralizeForCsv($val) {
  $result = ltrim($val, '=+-@');
  return str_replace('"', '""', $result);
}
define("APP_VERSION", "1.19.23.5325");
        if ($bean->getAttribute($checkbox_control_name)) print ',"'.ttNeutralizeForCsv($userField['label']).'"';
        if ($bean->getAttribute($checkbox_control_name)) print ',"'.ttNeutralizeForCsv($timeField['label']).'"';
      if ($user->can('view_reports') || $user->can('view_all_reports') || $user->isClient()) print ',"'.ttNeutralizeForCsv($item['user']).'"';
          if ($bean->getAttribute($checkbox_control_name)) print ',"'.ttNeutralizeForCsv($item[$field_name]).'"';
      if ($bean->getAttribute('chclient')) print ',"'.ttNeutralizeForCsv($item['client']).'"';
      if ($bean->getAttribute('chproject')) print ',"'.ttNeutralizeForCsv($item['project']).'"';
      if ($bean->getAttribute('chtask')) print ',"'.ttNeutralizeForCsv($item['task']).'"';
          if ($bean->getAttribute($checkbox_control_name)) print ',"'.ttNeutralizeForCsv($item[$field_name]).'"';
      if ($bean->getAttribute('chnote')) print ',"'.ttNeutralizeForCsv($item['note']).'"';
      if ($bean->getAttribute('chinvoice')) print ',"'.ttNeutralizeForCsv($item['invoice']).'"';
      if ($bean->getAttribute('chtimesheet')) print ',"'.ttNeutralizeForCsv($item['timesheet_name']).'"';