Add config param $dolibarr_main_restrict_eval_methods with whitelist of

functionsallowed in dol_eval. Advisory GHSA-x3w7-24rq-gvc5
This commit is contained in:
Laurent Destailleur
2025-11-19 03:44:24 +01:00
parent 63cca7f128
commit d858764b15
4 changed files with 224 additions and 213 deletions

View File

@@ -617,6 +617,12 @@ class SecurityTest extends CommonClassTest
$conf->global->MAIN_ALLOW_DOUBLE_COLON_IN_DOL_EVAL = 0;
$conf->global->MAIN_ALLOW_OBFUSCATION_METHODS_IN_DOL_EVAL = 1;
// We force $dolibarr_main_restrict_eval_methods to empty, so the code will use the old black-list patterns.
global $dolibarr_main_restrict_eval_methods;
print "\ndolibarr_main_restrict_eval_methods = ".$dolibarr_main_restrict_eval_methods."\n";
//$dolibarr_main_restrict_eval_methods = array();
//$resulttest = dol_eval('((getDolGlobalString("MAIN_USE_ADVANCED_PERMS") ? $user->hasRight("user","group_advance","read") : $user->hasRight("user","user","lire")) || $user->admin) && !(isModEnabled("multicompany") && $conf->entity > 1 && getDolGlobalString("MULTICOMPANY_TRANSVERSE_MODE"))', 1, 0);
//print "resulttest = ".$resulttest."\n";
@@ -630,22 +636,22 @@ class SecurityTest extends CommonClassTest
print "result2 = ".$result."\n";
$this->assertFalse($result);
$s = '((($reloadedobj = new ClassThatDoesNotExists($db)) && ($reloadedobj->fetchNoCompute($objectoffield->fk_product) > 0)) ? \'1\' : \'0\')';
$s = '((($var1 = new ClassThatDoesNotExists($db)) && ($var1->fetchNoCompute($objectoffield->fk_product) > 0)) ? \'1\' : \'0\')';
$result3a = dol_eval($s, 1, 1, '2');
print "result3a = ".$result3a."\n";
$this->assertStringContainsString('Exception during evaluation: '.$s, $result3a);
$s = '((($reloadedobj = new Project($db)) && ($reloadedobj->fetchNoCompute($objectoffield->fk_product) > 0)) ? \'1\' : \'0\')';
$s = '((($var1 = new Project($db)) && ($var1->fetchNoCompute($objectoffield->fk_product) > 0)) ? \'1\' : \'0\')';
$result3b = dol_eval($s, 1, 1, '2');
print "result3b = ".$result."\n";
$this->assertEquals('0', $result3b);
$s = '(($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"';
$s = '(($var1 = new Task($db)) && ($var1->fetchNoCompute($objectoffield->id) > 0) && ($var2 = new Project($db)) && ($var2->fetchNoCompute($var1->fk_project) > 0)) ? $var2->ref : "Parent project not found"';
$result = (string) dol_eval($s, 1, 1, '2');
print "result3c = ".$result."\n";
$this->assertEquals('Parent project not found', $result);
$s = '(($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\'';
$s = '(($var1 = new Task($db)) && ($var1->fetchNoCompute($objectoffield->id) > 0) && ($var2 = new Project($db)) && ($var2->fetchNoCompute($var1->fk_project) > 0)) ? $var2->ref : \'Parent project not found\'';
$result = (string) dol_eval($s, 1, 1, '2');
print "result4 = ".$result."\n";
$this->assertEquals('Parent project not found', $result, 'Test 4');
@@ -659,12 +665,12 @@ class SecurityTest extends CommonClassTest
print "result6 = ".$result."\n";
$this->assertEquals('1', $result, 'Test 5');
/*
$s = 'MyClass::MyMethod()';
$result = dol_eval($s, 1, 1, '2');
print "result7 = ".$result."\n";
$this->assertStringContainsString('Bad string syntax to evaluate (double : char is forbidden without setting MAIN_ALLOW_DOUBLE_COLON_IN_DOL_EVAL)', $result);
$this->assertStringContainsString('Bad string syntax to evaluate (double : char is forbidden without setting MAIN_ALLOW_DOUBLE_COLON_IN_DOL_EVAL)', $result, 'The string was not detected as evil');
*/
/* not allowed. Not a one line eval string
$result = (string) dol_eval('if ($a == 1) { }', 1, 1);
@@ -718,21 +724,21 @@ class SecurityTest extends CommonClassTest
print "result7 = ".$result."\n";
$this->assertStringContainsString('Bad string syntax to evaluate (found chars that are not chars for a simple one line clean eval string)', $result, 'The string was not detected as evil');
$result = (string) dol_eval('$a=exec("ls")', 1, 1);
$result = (string) dol_eval('$var1=exec("ls")', 1, 1);
print "result7 = ".$result."\n";
$this->assertStringContainsString('Bad string syntax to evaluate (mode 1, found call of a function or method without using the direct name of the function)', $result, 'The string was not detected as evil');
$this->assertStringContainsString('Bad string syntax to evaluate', $result, 'The string was not detected as evil');
$result = (string) dol_eval('$a=exec(\'ls\')', 1, 1);
$result = (string) dol_eval('$var1=exec(\'ls\')', 1, 1);
print "result7 = ".$result."\n";
$this->assertStringContainsString('Bad string syntax to evaluate (mode 1, found call of a function or method without using the direct name of the function)', $result, 'The string was not detected as evil');
$this->assertStringContainsString('Bad string syntax to evaluate', $result, 'The string was not detected as evil');
$result = (string) dol_eval('$a=exec ("ls")', 1, 1);
$result = (string) dol_eval('$var1=exec ("ls")', 1, 1);
print "result8 = ".$result."\n";
$this->assertStringContainsString('Bad string syntax to evaluate', $result, 'The string was not detected as evil');
$result = (string) dol_eval("strrev('metsys') ('whoami')", 1, 1);
print "result8b = ".$result."\n";
$this->assertStringContainsString('Bad string syntax to evaluate (mode 1, found call of a function or method without using the direct name of the function)', $result, 'The string was not detected as evil');
$this->assertStringContainsString('Bad string syntax to evaluate', $result, 'The string was not detected as evil');
$conf->global->MAIN_ALLOW_OBFUSCATION_METHODS_IN_DOL_EVAL = 0;
@@ -746,11 +752,11 @@ class SecurityTest extends CommonClassTest
$result = (string) dol_eval("('ex'.'ec')('ls')", 1, 0); // This will execute exec of ls
print "result11 = ".$result."\n";
$this->assertStringContainsString('Bad string syntax to evaluate (mode 1, found call of a function or method without using the direct name of the function)', $result, 'The string was not detected as evil');
$this->assertStringContainsString('Bad string syntax to evaluate', $result, 'The string was not detected as evil');
$result = (string) dol_eval("('ex'.'ec') /* */ (/* */'ls')", 1, 0); // This will execute exec of ls
print "result11 = ".$result."\n";
$this->assertStringContainsString('Bad string syntax to evaluate (mode 1, found call of a function or method without using the direct name of the function)', $result, 'The string was not detected as evil');
$this->assertStringContainsString('Bad string syntax to evaluate', $result, 'The string was not detected as evil');
$result = (string) dol_eval("sprintf(\"%s%s\", \"ex\", \"ec\")('echo abc')", 1, 0);
print "result12 = ".$result."\n";
@@ -825,7 +831,7 @@ class SecurityTest extends CommonClassTest
$leftmenu = 'ab';
$result = (string) dol_eval("(\$leftmenu.'s')", 1, 0);
print "resultconcat3 = ".$result."\n";
$this->assertStringContainsString('Bad string syntax to evaluate (dot char is forbidden)', $result, 'Test concat - The string was not reported as a bad syntax when it should');
$this->assertStringContainsString('Bad string syntax to evaluate (dot char is forbidden if not strictly between 2 numbers)', $result, 'Test concat - The string was not reported as a bad syntax when it should');
// Not allowed
@@ -847,11 +853,15 @@ class SecurityTest extends CommonClassTest
$result = (string) dol_eval('\'exec\'("aaa")', 1, 0);
print "result23 = ".$result."\n";
$this->assertStringContainsString('Bad string syntax to evaluate', json_encode($result), 'Test 23 - The string was not detected as evil - Can\'t find the string Bad string syntax when i should');
$this->assertStringContainsString('Bad string syntax to evaluate', json_encode($result), 'Test 23 - The string was not detected as evil - Can\'t find the string Bad string syntax when it should');
$result = (string) dol_eval('1 + 2 <? echo "aaa" ?>', 1, 0, '2');
print "result24 = ".$result."\n";
$this->assertStringContainsString('Bad string syntax to evaluate (The char ? can be used only with a space before and after)', json_encode($result), 'Test 24 - The string was not detected as evil - Can\'t find the string Bad string syntax when i should');
$result = (string) dol_eval('$$a', 1, 0);
print "result25 = ".$result."\n";
$this->assertStringContainsString('Bad string syntax to evaluate', json_encode($result), 'Test 25 - The string was not detected as evil - Can\'t find the string Bad string syntax when i should');
}