diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 701b34c4042..3150ea706cc 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -8914,7 +8914,6 @@ function verifCond($strToEvaluate) */ function dol_eval($s, $returnvalue = 0, $hideerrors = 1, $onlysimplestring = '1') { - try { // Only global variables can be changed by eval function and returned to caller global $db, $langs, $user, $conf, $website, $websitepage; global $action, $mainmenu, $leftmenu; @@ -8925,106 +8924,110 @@ function dol_eval($s, $returnvalue = 0, $hideerrors = 1, $onlysimplestring = '1' global $obj; // To get $obj used into list when dol_eval is used for computed fields and $obj is not yet $object global $soc; // For backward compatibility - // Test on dangerous char (used for RCE), we allow only characters to make PHP variable testing - if ($onlysimplestring == '1') { - // We must accept: '1 && getDolGlobalInt("doesnotexist1") && $conf->global->MAIN_FEATURES_LEVEL' - // We must accept: '$conf->barcode->enabled || preg_match(\'/^AAA/\',$leftmenu)' - // We must accept: '$user->rights->cabinetmed->read && !$object->canvas=="patient@cabinetmed"' - if (preg_match('/[^a-z0-9\s'.preg_quote('^$_+-.*>&|=!?():"\',/@', '/').']/i', $s)) { - if ($returnvalue) { - return 'Bad string syntax to evaluate (found chars that are not chars for simplestring): '.$s; - } else { - dol_syslog('Bad string syntax to evaluate (found chars that are not chars for simplestring): '.$s); - return ''; + try { + // Test on dangerous char (used for RCE), we allow only characters to make PHP variable testing + if ($onlysimplestring == '1') { + // We must accept: '1 && getDolGlobalInt("doesnotexist1") && $conf->global->MAIN_FEATURES_LEVEL' + // We must accept: '$conf->barcode->enabled || preg_match(\'/^AAA/\',$leftmenu)' + // We must accept: '$user->rights->cabinetmed->read && !$object->canvas=="patient@cabinetmed"' + if (preg_match('/[^a-z0-9\s'.preg_quote('^$_+-.*>&|=!?():"\',/@', '/').']/i', $s)) { + if ($returnvalue) { + return 'Bad string syntax to evaluate (found chars that are not chars for simplestring): '.$s; + } else { + dol_syslog('Bad string syntax to evaluate (found chars that are not chars for simplestring): '.$s); + return ''; + } + // TODO + // We can exclude all parenthesis ( that are not '($db' and 'getDolGlobalInt(' and 'getDolGlobalString(' and 'preg_match(' and 'isModEnabled(' + // ... + } + } elseif ($onlysimplestring == '2') { + // We must accept: (($reloadedobj = new Task($db)) && ($reloadedobj->fetchNoCompute($object->id) > 0) && ($secondloadedobj = new Project($db)) && ($secondloadedobj->fetchNoCompute($reloadedobj->fk_project) > 0)) ? $secondloadedobj->ref : "Parent project not found" + if (preg_match('/[^a-z0-9\s'.preg_quote('^$_+-.*>&|=!?():"\',/@;[]', '/').']/i', $s)) { + if ($returnvalue) { + return 'Bad string syntax to evaluate (found chars that are not chars for simplestring): '.$s; + } else { + dol_syslog('Bad string syntax to evaluate (found chars that are not chars for simplestring): '.$s); + return ''; + } } - // TODO - // We can exclude all parenthesis ( that are not '($db' and 'getDolGlobalInt(' and 'getDolGlobalString(' and 'preg_match(' and 'isModEnabled(' - // ... } - } elseif ($onlysimplestring == '2') { - // We must accept: (($reloadedobj = new Task($db)) && ($reloadedobj->fetchNoCompute($object->id) > 0) && ($secondloadedobj = new Project($db)) && ($secondloadedobj->fetchNoCompute($reloadedobj->fk_project) > 0)) ? $secondloadedobj->ref : "Parent project not found" - if (preg_match('/[^a-z0-9\s'.preg_quote('^$_+-.*>&|=!?():"\',/@;[]', '/').']/i', $s)) { + if (strpos($s, '::') !== false) { if ($returnvalue) { - return 'Bad string syntax to evaluate (found chars that are not chars for simplestring): '.$s; + return 'Bad string syntax to evaluate (double : char is forbidden): '.$s; } else { - dol_syslog('Bad string syntax to evaluate (found chars that are not chars for simplestring): '.$s); + dol_syslog('Bad string syntax to evaluate (double : char is forbidden): '.$s); return ''; } } - } - if (strpos($s, '::') !== false) { - if ($returnvalue) { - return 'Bad string syntax to evaluate (double : char is forbidden): '.$s; - } else { - dol_syslog('Bad string syntax to evaluate (double : char is forbidden): '.$s); - return ''; + if (strpos($s, '`') !== false) { + if ($returnvalue) { + return 'Bad string syntax to evaluate (backtick char is forbidden): '.$s; + } else { + dol_syslog('Bad string syntax to evaluate (backtick char is forbidden): '.$s); + return ''; + } } - } - if (strpos($s, '`') !== false) { - if ($returnvalue) { - return 'Bad string syntax to evaluate (backtick char is forbidden): '.$s; - } else { - dol_syslog('Bad string syntax to evaluate (backtick char is forbidden): '.$s); - return ''; + if (preg_match('/[^0-9]+\.[^0-9]+/', $s)) { // We refuse . if not between 2 numbers + if ($returnvalue) { + return 'Bad string syntax to evaluate (dot char is forbidden): '.$s; + } else { + dol_syslog('Bad string syntax to evaluate (dot char is forbidden): '.$s); + return ''; + } } - } - if (preg_match('/[^0-9]+\.[^0-9]+/', $s)) { // We refuse . if not between 2 numbers - if ($returnvalue) { - return 'Bad string syntax to evaluate (dot char is forbidden): '.$s; - } else { - dol_syslog('Bad string syntax to evaluate (dot char is forbidden): '.$s); - return ''; + + // We block use of php exec or php file functions + $forbiddenphpstrings = array('$$'); + $forbiddenphpstrings = array_merge($forbiddenphpstrings, array('_ENV', '_SESSION', '_COOKIE', '_GET', '_POST', '_REQUEST')); + + $forbiddenphpfunctions = array("exec", "passthru", "shell_exec", "system", "proc_open", "popen", "eval", "dol_eval", "executeCLI", "verifCond", "base64_decode"); + $forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("fopen", "file_put_contents", "fputs", "fputscsv", "fwrite", "fpassthru", "require", "include", "mkdir", "rmdir", "symlink", "touch", "unlink", "umask")); + $forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("function", "call_user_func")); + + $forbiddenphpregex = 'global\s+\$|\b('.implode('|', $forbiddenphpfunctions).')\b'; + + do { + $oldstringtoclean = $s; + $s = str_ireplace($forbiddenphpstrings, '__forbiddenstring__', $s); + $s = preg_replace('/'.$forbiddenphpregex.'/i', '__forbiddenstring__', $s); + //$s = preg_replace('/\$[a-zA-Z0-9_\->\$]+\(/i', '', $s); // Remove $function( call and $mycall->mymethod( + } while ($oldstringtoclean != $s); + + if (strpos($s, '__forbiddenstring__') !== false) { + dol_syslog('Bad string syntax to evaluate: '.$s, LOG_WARNING); + if ($returnvalue) { + return 'Bad string syntax to evaluate: '.$s; + } else { + dol_syslog('Bad string syntax to evaluate: '.$s); + return ''; + } } - } - // We block use of php exec or php file functions - $forbiddenphpstrings = array('$$'); - $forbiddenphpstrings = array_merge($forbiddenphpstrings, array('_ENV', '_SESSION', '_COOKIE', '_GET', '_POST', '_REQUEST')); - - $forbiddenphpfunctions = array("exec", "passthru", "shell_exec", "system", "proc_open", "popen", "eval", "dol_eval", "executeCLI", "verifCond", "base64_decode"); - $forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("fopen", "file_put_contents", "fputs", "fputscsv", "fwrite", "fpassthru", "require", "include", "mkdir", "rmdir", "symlink", "touch", "unlink", "umask")); - $forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("function", "call_user_func")); - - $forbiddenphpregex = 'global\s+\$|\b('.implode('|', $forbiddenphpfunctions).')\b'; - - do { - $oldstringtoclean = $s; - $s = str_ireplace($forbiddenphpstrings, '__forbiddenstring__', $s); - $s = preg_replace('/'.$forbiddenphpregex.'/i', '__forbiddenstring__', $s); - //$s = preg_replace('/\$[a-zA-Z0-9_\->\$]+\(/i', '', $s); // Remove $function( call and $mycall->mymethod( - } while ($oldstringtoclean != $s); - - if (strpos($s, '__forbiddenstring__') !== false) { - dol_syslog('Bad string syntax to evaluate: '.$s, LOG_WARNING); + //print $s."
\n"; if ($returnvalue) { - return 'Bad string syntax to evaluate: '.$s; + if ($hideerrors) { + return @eval('return '.$s.';'); + } else { + return eval('return '.$s.';'); + } } else { - dol_syslog('Bad string syntax to evaluate: '.$s); - return ''; + if ($hideerrors) { + @eval($s); + } else { + eval($s); + } } + } catch (Error $e) { + $error = 'Caught error : '; + $error .= $e->getMessage(); + //$error .= ', Trace : '; + //$error .= json_encode($e->getTrace()); + error_log($error, 1); } - - //print $s."
\n"; if ($returnvalue) { - if ($hideerrors) { - return @eval('return '.$s.';'); - } else { - return eval('return '.$s.';'); - } - } else { - if ($hideerrors) { - @eval($s); - } else { - eval($s); - } + return ''; } - } catch (Error $e) { - $error = 'Caught error : '; - $error .= $e->getMessage() . ', '; - $error .= 'Trace : '; - $error .= json_encode($e->getTrace()); - error_log($error, 1); - } } /**