CVE-2022-4766 (published 2022-12-27T13:15Z)

A vulnerability was found in dolibarr_project_timesheet up to 4.5.5. It has been declared as problematic. This vulnerability affects unknown code of the component Form Handler. The manipulation leads to cross-site request forgery. The attack can be initiated remotely. Upgrading to version 4.5.6.a is able to address this issue. The name of the patch is 082282e9dab43963e6c8f03cfaddd7921de377f4. It is recommended to upgrade the affected component. The identifier of this vulnerability is VDB-216880.

CVSS v3 base score: 6.5, MEDIUM (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N)

Weakness information:
cwe_id: CWE-352
cwe_name: Cross-Site Request Forgery (CSRF)
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.
extended_description: When a web server is designed to receive a request from a client without any mechanism for verifying that it was intentionally sent, then it might be possible for an attacker to trick a client into making an unintentional request to the web server which will be treated as an authentic request. This can be done via a URL, image load, XMLHttpRequest, etc. and can result in exposure of data or unintended code execution.
         

Fix information:
repo_url: https://github.com/delcroip/dolibarr_project_timesheet
commit_details: repo_url: https://github.com/delcroip/dolibarr_project_timesheet
author: Patrick Delcroix
author_date: 2022-08-04 00:07:14+02:00
msg: csrf token in all form
repository: repo_url: https://github.com/delcroip/dolibarr_project_timesheet
repo_name: delcroip/dolibarr_project_timesheet
description: Timesheet view for project in Dolibarr
repo_language: PHP
owner: delcroip
file_changes: filename: AttendanceEventAdmin.php
change_type: ModificationType.MODIFY
diff: @@ -515,6 +515,8 @@ if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
         dol_print_error($db);
     }
     print '</table>'."\n";
+    print '<input type = "hidden" id="csrf-token" name = "token" value = "'.$token.'"/>';
+
     print '</form>'."\n";
     // new button
    // print '<a href = "attendanceeventCard.php?action=create" class="butAction"role="button">'.$langs->trans('New');

programming_language: PHP
filename: ChangeLog.md
change_type: ModificationType.MODIFY
diff: @@ -1,4 +1,8 @@
 # dolibarr_project_timesheet changelog
+4.5.6
+- fix csrf issue in other pages
+- fix box issue
+
 4.5.5
 - fix: pdf header with small pictures
 - misc: white logo

programming_language: Markdown
filename: TimesheetProjectInvoice.php
change_type: ModificationType.MODIFY
diff: @@ -25,6 +25,7 @@ define('$conf->global->TIMESHEET_INVOICE_SHOW_USER', '1');
 include 'core/lib/includeMain.lib.php';
 include 'core/lib/generic.lib.php';
 include 'core/lib/timesheet.lib.php';
+$token = getToken();
 require_once DOL_DOCUMENT_ROOT .'/core/lib/functions.lib.php';
 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
 require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
@@ -105,6 +106,8 @@ $langs->load('timesheet@timesheet');
             $Form .= '<input type = "hidden" name = "socid" value = "'.$socid.'">';
             $Form .= '<input type = "hidden" name = "invoicingMethod" value = "'.$mode.'">';
             $Form .= '<input type = "hidden" name = "ts2Invoice" value = "'.$ts2Invoice.'">';
+            $Form .= '<input type = "hidden" id="csrf-token" name = "token" value = "'.$token.'"/>';
+
             $resql = $db->query($sql);
             $num = 0;
             $resArray = array();
@@ -492,6 +495,7 @@ $langs->load('timesheet@timesheet');
             //    $sqlTailWhere .= ' AND fk_socpeople = \''.$userid.'\' and t.fk_statut = \'1\'';
             //}
             $Form = '<form name = "settings" action="?step=2" method = "POST" >'."\n\t";
+            $Form .= '<input type = "hidden" id="csrf-token" name = "token" value = "'.$token.'"/>';
             $Form .= '<table class = "noborder" width = "100%">'."\n\t\t";
             $Form .= '<tr class = "liste_titre" width = "100%" ><th colspan = "2">'
                 .$langs->trans('generalInvoiceProjectParam').'</th></tr>';

programming_language: PHP
filename: TimesheetReportProject.php
change_type: ModificationType.MODIFY
diff: @@ -228,6 +228,9 @@ $form_output .= '<form action="?action=reportproject'.(($optioncss != '')?'&amp;
         <td></td>
         </tr>
         <tr >';
+$token = getToken();
+$form_output .= '<input type = "hidden" id="csrf-token" name = "token" value = "'.$token.'"/>';
+
 
 if($hidetab == 1){
         $form_output .='<td><select  name = "projectSelected">';
@@ -295,19 +298,19 @@ if (!empty($querryRes))$form_output .=
     .dol_print_date($dateStart, 'dayxcard').'&dateEnd='
     .dol_print_date($dateEnd, 'dayxcard').'&projectSelected='
     .$projectSelectedId.'&mode='.$mode.'&invoicabletaskOnly='.$invoicabletaskOnly
-    ."&hidetab=".$hidetab.'&ungroup='.$ungroup.'" >'.$langs->trans('TimesheetPDF').'</a>';
+    ."&hidetab=".$hidetab.'&ungroup='.$ungroup.'&token='.$token.'" >'.$langs->trans('TimesheetPDF').'</a>';
 if (!empty($querryRes) && $conf->global->MAIN_MODULE_EXPORT)$form_output .=
     '<a class = "butAction" href="?action=getExport&dateStart='
     .dol_print_date($dateStart, 'dayxcard').'&dateEnd='
     .dol_print_date($dateEnd, 'dayxcard').'&projectSelected='.$projectSelectedId
     .'&mode='.$mode.'&model='.$model.'&invoicabletaskOnly='.$invoicabletaskOnly
-    ."&hidetab=".$hidetab.'&ungroup='.$ungroup.'" >'.$langs->trans('Export').'</a>';
+    ."&hidetab=".$hidetab.'&ungroup='.$ungroup.'&token='.$token.'" >'.$langs->trans('Export').'</a>';
 if (!empty($querryRes))$form_output .=
     '<a class = "butAction" href="?action=reportproject&dateStart='
     .dol_print_date($dateStart, 'dayxcard').'&dateEnd='
     .dol_print_date($dateEnd, 'dayxcard').'&projectSelected='.$projectSelectedId
     .'&mode='.$mode.'&invoicabletaskOnly='.$invoicabletaskOnly
-    ."&hidetab=".$hidetab.'&ungroup='.$ungroup.'" >'.$langs->trans('Refresh').'</a>';
+    ."&hidetab=".$hidetab.'&ungroup='.$ungroup.'&token='.$token.'" >'.$langs->trans('Refresh').'</a>';
 $form_output .= '</form>';
 if (!($optioncss != '' && !empty($_POST['userSelected']))) echo $form_output;
 echo $querryRes;

programming_language: PHP
filename: TimesheetReportUser.php
change_type: ModificationType.MODIFY
diff: @@ -163,6 +163,9 @@ $form_output .= '<form action="?action=reportUser'.(($optioncss != '')?'&amp;opt
         <tr >
         <td>
         ';
+$token = getToken();
+$form_output .= '<input type = "hidden" id="csrf-token" name = "token" value = "'.$token.'"/>';
+
 if($admin){
     $form_output .= $form->select_dolusers($userIdSelected, 'userSelected');
 
@@ -237,7 +240,7 @@ if ( ! empty( $querryRes ) && $conf->global->MAIN_MODULE_EXPORT ) {
         .'&invoicabletaskOnly=' . $invoicabletaskOnly 
         .'&ungroup=' . $ungroup 
         .'&showAll=' . $show_all 
-        . '" >' . $langs->trans( 'Export' ) . '</a>';
+        . '&token='.$token.'" >' . $langs->trans( 'Export' ) . '</a>';
 }
 if ( ! empty( $querryRes ) ) {
 	$form_output .= '<a class = "butAction" href="?action=getpdf&dateStart=' 
@@ -248,7 +251,7 @@ if ( ! empty( $querryRes ) ) {
     . '&invoicabletaskOnly='  . $invoicabletaskOnly 
     . '&ungroup=' . $ungroup 
     . '&showAll=' . $show_all 
-    . '" >' . $langs->trans( 'PDF' ) . '</a>';
+    . '&token='.$token.'" >' . $langs->trans( 'PDF' ) . '</a>';
 }
 $form_output .= '</div></div></form>';
 

programming_language: PHP
filename: TimesheetTeamApproval.php
change_type: ModificationType.MODIFY
diff: @@ -365,6 +365,8 @@ function getHTMLNavigation($optioncss, $selectList, $current = 0)
     }
     $Nav .= "</th>\n\t\t<th>\n\t\t\t";
     $Nav .= '<form name = "goTo" action="?action=goTo" method = "POST" >'."\n\t\t\t";
+    $Nav .= '<input type = "hidden" id="csrf-token" name = "token" value = "'.$token.'"/>';
+
     $Nav .= $langs->trans("GoTo").': '.$htmlSelect."\n\t\t\t";;
     $Nav .= '<input type = "submit" value = "Go" /></form>'."\n\t\t</th>\n\t\t<th>\n\t\t\t";
     if ($current<count($selectList)) {

programming_language: PHP
filename: TimesheetUserTasksAdmin.php
change_type: ModificationType.MODIFY
diff: @@ -556,6 +556,7 @@ switch($action) {
             //print_barre_liste function defined in /core/lib/function.lib.php, possible to add a picto
             print_barre_liste($langs->trans("Timesheetuser"), $page, $PHP_SELF, $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords);
             print '<form method = "POST" action = "'.$_SERVER["PHP_SELF"].'">';
+            print '<input type = "hidden" id="csrf-token" name = "token" value = "'.$token.'"/>';
             print '<table class = "liste" style = "border-collapse:separate;" width = "100%">'."\n";
             //TITLE
             print '<tr class = "liste_titre">';

programming_language: PHP
filename: timesheetsetup.php
change_type: ModificationType.MODIFY
diff: @@ -360,6 +360,8 @@ print '<span class="opacitymedium">'.$langs->trans("GeneralTabDesc").'</span>';
 print load_fiche_titre( $langs->trans( "GeneralOption" ), '', '' );
 
 echo '<form name="settings" action="?action=save" method="POST">';
+$token = getToken();
+echo '<input type = "hidden" id="csrf-token" name = "token" value = "'.$token.'"/>';
 echo '<table class="noborder" width = "100%">';
 echo '<tr class="liste_titre" width = "100%" ><th width = "200px">'.$langs->trans("Name").'</th><th>';
 echo $langs->trans("Description").'</th><th>'.$langs->trans("Value")."</th></tr>";

programming_language: PHP
filename: AttendanceEvent.class.php
change_type: ModificationType.MODIFY
diff: @@ -758,6 +758,9 @@ public function getHTMLGetOtherUserTs($idsList, $selected, $admin)
          $HTML .= $form->select_dolusers($selected, 'userid');
     }
     $HTML .= '<input type = "submit" value = "'.$langs->trans('Submit').'"/></form> ';
+    //FIXME should take token as input
+    $token = getToken();
+    $HTML .= '<input type = "hidden" id="csrf-token" name = "token" value = "'.$token.'"/>';
 
     return $HTML;
 }

programming_language: PHP
filename: TimesheetUserTasks.class.php
change_type: ModificationType.MODIFY
diff: @@ -1061,33 +1061,25 @@ public function getHTMLNavigation($optioncss, $ajax = false)
     global $langs, $conf;
     $form = new Form($this->db);
     $tail = '';
-    //$tail = '&wlm='.$this->whitelistmode;
     if (isset($conf->global->TIMESHEET_ADD_FOR_OTHER) 
         && $conf->global->TIMESHEET_ADD_FOR_OTHER == 1){
         $tail = '&userid='.$this->userId;
     }
     $Nav = '<table class = "noborder" width = "50%">'."\n\t".'<tr>'."\n\t\t".'<th>'."\n\t\t\t";
     if ($ajax) {
-//     $Nav .= '<a id = "navPrev" onClick = "loadXMLTimesheet(\''.getStartDate($this->date_start, -1).'\', 0);';
     } else{
         $Nav .= '<a href="?dateStart='.getStartDate($this->date_start, -1).$tail;
     }
     if ($optioncss != '')$Nav .= '&amp;optioncss='.$optioncss;
     $Nav .= '">  &lt;&lt;'.$langs->trans("Previous").' </a>'."\n\t\t</th>\n\t\t<th>\n\t\t\t";
-//  if ($ajax)
-//  {
-    //    $Nav .= '<form name = "goToDate" onsubmit = "return toDateHandler();" action="?action=goToDate&wlm='.$this->whitelistmode.'" method = "POST">'."\n\t\t\t";
-    //} else{
-        $Nav .= '<form name = "goToDate" action="?action=goToDate'.$tail.'" method = "POST" >'."\n\t\t\t";
-    //}
+    $Nav .= '<form name = "goToDate" action="?action=goToDate'.$tail.'" method = "POST" >'."\n\t\t\t";
+    //FIXME should take token as input
+    $token = getToken();
+    $Nav .= '<input type = "hidden" id="csrf-token" name = "token" value = "'.$token.'"/>';
+
     $Nav .= $langs->trans("GoTo").': '.$form->select_date(-1, 'toDate', 0, 0, 0, "", 1, 1, 1)."\n\t\t\t";;
     $Nav .= '<input type = "submit" value = "Go" /></form>'."\n\t\t</th>\n\t\t<th>\n\t\t\t";
-    //if ($ajax)
-//    {
-    //    $Nav .= '<a id = "navNext" onClick = "loadXMLTimesheet(\''.getStartDate($this->date_start, 1).'\', 0);';
-    //} else{
-        $Nav .= '<a href="?dateStart='.getStartDate($this->date_start, 1).$tail;
-    //}
+    $Nav .= '<a href="?dateStart='.getStartDate($this->date_start, 1).$tail;
     if ($optioncss != '') $Nav .= '&amp;optioncss='.$optioncss;
     $Nav .= '">'.$langs->trans("Next").' &gt;&gt;</a>'."\n\t\t</th>\n\t</tr>\n </table>\n";
     return $Nav;
@@ -1155,7 +1147,12 @@ public function getHTMLNavigation($optioncss, $ajax = false)
         } else{
             $HTML .= $form->select_dolusers($selected, 'userid');
         }
+        //FIXME should take token as input
+        $token = getToken();
+        $HTML .= '<input type = "hidden" id="csrf-token" name = "token" value = "'.$token.'"/>';
+
         $HTML .= '<input type = "submit" value = "'.$langs->trans('Submit').'"/></form> ';
+        
         return $HTML;
     }
     /**

programming_language: PHP
filename: modtimesheet.class.php
change_type: ModificationType.MODIFY
diff: @@ -54,7 +54,7 @@ class modTimesheet extends DolibarrModules
 		        $this->editor_name = 'Patrick Delcroix';
 		        $this->editor_url = 'https://github.com/delcroip';
                 // Possible values for version are: 'development', 'experimental', 'dolibarr' or version
-                $this->version = '4.5.4';
+                $this->version = '4.5.6';
                 // Key used in llx_cons table to save module status enabled/disabled(where timesheet is value of property name of module in uppercase)
                 $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name);
                 // Where to store the module in setup page(0=common, 1=interface, 2=others, 3=very specific)

programming_language: PHP