diff --git a/htdocs/categories/info.php b/htdocs/categories/info.php index 5666664b848..f5b54f50de9 100644 --- a/htdocs/categories/info.php +++ b/htdocs/categories/info.php @@ -71,11 +71,11 @@ $title = Categorie::$MAP_TYPE_TITLE_AREA[$type]; $head = categories_prepare_head($object, $type); print dol_get_fiche_head($head, 'info', $langs->trans($title), -1, 'category'); -$backtolist = (GETPOST('backtolist') ? GETPOST('backtolist') : DOL_URL_ROOT.'/categories/index.php?leftmenu=cat&type='.$type); -$linkback = ''.$langs->trans("BackToList").''; +$backtolist = (GETPOST('backtolist') ? GETPOST('backtolist') : DOL_URL_ROOT.'/categories/index.php?leftmenu=cat&type='.urlencode($type)); +$linkback = ''.$langs->trans("BackToList").''; $object->next_prev_filter = ' type = '.$object->type; $object->ref = $object->label; -$morehtmlref = '
'.$langs->trans("Root").' >> '; +$morehtmlref = '
'.$langs->trans("Root").' >> '; $ways = $object->print_all_ways(" >> ", '', 1); foreach ($ways as $way) { $morehtmlref .= $way."
\n"; diff --git a/htdocs/categories/photos.php b/htdocs/categories/photos.php index cfc722df83f..c7e574939ff 100644 --- a/htdocs/categories/photos.php +++ b/htdocs/categories/photos.php @@ -108,7 +108,8 @@ if ($object->id) { $head = categories_prepare_head($object, $type); print dol_get_fiche_head($head, 'photos', $langs->trans($title), -1, 'category'); - $linkback = ''.$langs->trans("BackToList").''; + $backtolist = (GETPOST('backtolist') ? GETPOST('backtolist') : DOL_URL_ROOT.'/categories/index.php?leftmenu=cat&type='.urlencode($type)); + $linkback = ''.$langs->trans("BackToList").''; $object->next_prev_filter = ' type = '.$object->type; $object->ref = $object->label; $morehtmlref = '
'.$langs->trans("Root").' >> '; diff --git a/htdocs/categories/traduction.php b/htdocs/categories/traduction.php index 9f2ed6936ef..de59aca376d 100644 --- a/htdocs/categories/traduction.php +++ b/htdocs/categories/traduction.php @@ -184,7 +184,8 @@ if (!empty($object->multilangs)) { print dol_get_fiche_head($head, 'translation', $langs->trans($title), -1, 'category'); -$linkback = ''.$langs->trans("BackToList").''; +$backtolist = (GETPOST('backtolist') ? GETPOST('backtolist') : DOL_URL_ROOT.'/categories/index.php?leftmenu=cat&type='.urlencode($type)); +$linkback = ''.$langs->trans("BackToList").''; $object->next_prev_filter = ' type = '.$object->type; $object->ref = $object->label; $morehtmlref = '
'.$langs->trans("Root").' >> '; diff --git a/htdocs/categories/viewcat.php b/htdocs/categories/viewcat.php index 7f19194a3c3..dedb368202d 100644 --- a/htdocs/categories/viewcat.php +++ b/htdocs/categories/viewcat.php @@ -215,18 +215,18 @@ $title = Categorie::$MAP_TYPE_TITLE_AREA[$type]; $head = categories_prepare_head($object, $type); print dol_get_fiche_head($head, 'card', $langs->trans($title), -1, 'category'); -$backtolist = (GETPOST('backtolist') ? GETPOST('backtolist') : DOL_URL_ROOT.'/categories/index.php?leftmenu=cat&type='.$type); -$linkback = ''.$langs->trans("BackToList").''; +$backtolist = (GETPOST('backtolist') ? GETPOST('backtolist') : DOL_URL_ROOT.'/categories/index.php?leftmenu=cat&type='.urlencode($type)); +$linkback = ''.$langs->trans("BackToList").''; $object->next_prev_filter = ' type = '.$object->type; $object->ref = $object->label; -$morehtmlref = '
'.$langs->trans("Root").' >> '; +$morehtmlref = '
'.$langs->trans("Root").' >> '; $ways = $object->print_all_ways(" >> ", '', 1); foreach ($ways as $way) { $morehtmlref .= $way."
\n"; } $morehtmlref .= '
'; -dol_banner_tab($object, 'label', $linkback, ($user->socid ? 0 : 1), 'label', 'label', $morehtmlref, '&type='.$type, 0, '', '', 1); +dol_banner_tab($object, 'label', $linkback, ($user->socid ? 0 : 1), 'label', 'label', $morehtmlref, '&type='.urlencode($type), 0, '', '', 1); /* diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 5a7158831d2..4fc283b8082 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -611,7 +611,7 @@ function GETPOST($paramname, $check = 'alphanohtml', $method = 0, $filter = null } // Sanitizing for special parameters. There is no reason to allow the backtopage parameter to contains an external URL. - if ($paramname == 'backtopage') { + if ($paramname == 'backtopage' || $paramname == 'backtolist') { $out = str_replace('\\', '/', $out); $out = str_replace(array(':', '@'), '', $out); $out = preg_replace(array('/^[a-z]*\/\/+/i'), '', $out); @@ -1000,6 +1000,19 @@ function dol_sanitizePathName($str, $newstr = '_', $unaccent = 1) return dol_string_nospecial($unaccent ? dol_string_unaccent($str) : $str, $newstr, $filesystem_forbidden_chars); } +/** + * Clean a string to use it as an URL + * + * @param string $stringtoclean String to clean + * @return string Escaped string. + */ +function dol_sanitizeUrl($stringtoclean) +{ + $stringtoclean = str_replace('javascript', '', $stringtoclean); + + return $stringtoclean; +} + /** * Clean a string from all accent characters to be used as ref, login or by dol_sanitizeFileName * @@ -1098,7 +1111,6 @@ function dol_string_nounprintableascii($str, $removetabcrlf = 1) } } - /** * Returns text escaped for inclusion into javascript code * diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 0bf28c68d0e..ab33d5cdc3a 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -59,12 +59,16 @@ if (!empty($_SERVER['MAIN_SHOW_TUNING_INFO'])) { */ function testSqlAndScriptInject($val, $type) { - // Decode string first + // Decode string first bcause a lot of things are obfuscated by encoding or multiple encoding. // So assertEquals($expectedresult, $result, 'Error on testSqlAndScriptInject expected 0a'); + $this->assertEquals($expectedresult, $result, 'Error on testSqlAndScriptInject for PHP_SELF that should be ok'); $test = 'This is a < inside string with < and > also and tag like before the >'; $result=testSqlAndScriptInject($test, 0); @@ -203,7 +203,11 @@ class SecurityTest extends PHPUnit\Framework\TestCase $_SERVER["PHP_SELF"]='/DIR WITH SPACE/htdocs/admin/index.php?mainmenu=home&leftmenu=setup&username=weservices;badaction'; $result=testSqlAndScriptInject($_SERVER["PHP_SELF"], 2); - $this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject 1b'); + $this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject for PHP_SELF that should detect XSS'); + + $test = 'javascript&colon;alert(1)'; + $result=testSqlAndScriptInject($test, 0); + $this->assertEquals($expectedresult, $result, 'Error on testSqlAndScriptInject expected 1b'); $test=""; $result=testSqlAndScriptInject($test, 0); @@ -322,6 +326,7 @@ class SecurityTest extends PHPUnit\Framework\TestCase $_POST["param10"]='is_object($object) ? ($object->id < 10 ? round($object->id / 2, 2) : (2 * $user->id) * (int) substr($mysoc->zip, 1, 2)) : \'objnotdefined\''; $_POST["param11"]=' Name '; $_POST["param12"]='aaa'; + $_POST["param13"]='javascript%26colon%26%23x3B%3Balert(1)'; $result=GETPOST('id', 'int'); // Must return nothing print __METHOD__." result=".$result."\n"; @@ -426,7 +431,7 @@ class SecurityTest extends PHPUnit\Framework\TestCase print __METHOD__." result=".$result."\n"; $this->assertEquals(trim($_POST["param12"]), $result, 'Test a string with DOCTYPE and restricthtml'); - // Special test for GETPOST of backtopage parameter + // Special test for GETPOST of backtopage or backtolist parameter $_POST["backtopage"]='//www.google.com'; $result=GETPOST("backtopage"); @@ -438,8 +443,8 @@ class SecurityTest extends PHPUnit\Framework\TestCase print __METHOD__." result=".$result."\n"; $this->assertEquals('www.google.com', $result, 'Test for backtopage param'); - $_POST["backtopage"]='::HTTPS://www.google.com'; - $result=GETPOST("backtopage"); + $_POST["backtolist"]='::HTTPS://www.google.com'; + $result=GETPOST("backtolist"); print __METHOD__." result=".$result."\n"; $this->assertEquals('www.google.com', $result, 'Test for backtopage param');