From 5d51d0679b8335b6da2c25ece24edae4956c77be Mon Sep 17 00:00:00 2001 From: ldestailleur Date: Tue, 1 Apr 2025 17:53:33 +0200 Subject: [PATCH] Share not allowed extension into the method getExecutableContent() --- htdocs/admin/security_file.php | 10 +-- htdocs/admin/system/security.php | 125 +++++++++++++++++++----------- htdocs/core/lib/files.lib.php | 12 +-- htdocs/core/lib/functions.lib.php | 27 ++++++- 4 files changed, 113 insertions(+), 61 deletions(-) diff --git a/htdocs/admin/security_file.php b/htdocs/admin/security_file.php index 53c2761b4b0..42ade68a31f 100644 --- a/htdocs/admin/security_file.php +++ b/htdocs/admin/security_file.php @@ -166,7 +166,7 @@ if (isset($max)) { } print ''; print ''; -print ' '.$langs->trans("Kb"); +print ' '.$langs->trans("Kb"); print ''; print ''; @@ -176,7 +176,7 @@ print ''; print $form->textwithpicto($langs->trans("UMask"), $langs->trans("UMaskExplanation")); print ''; print ''; -print ''; +print ''; print ''; print ''; @@ -197,7 +197,7 @@ if (ini_get('safe_mode') && getDolGlobalString('MAIN_ANTIVIRUS_COMMAND')) { dol_syslog("safe_mode is on, basedir is ".$basedir.", safe_mode_exec_dir is ".ini_get('safe_mode_exec_dir'), LOG_WARNING); } } -print ''; +print ''; if (defined('MAIN_ANTIVIRUS_COMMAND') && !defined('MAIN_ANTIVIRUS_BYPASS_COMMAND_AND_PARAM')) { print '
'.$langs->trans("ValueIsForcedBySystem").''; } @@ -211,7 +211,7 @@ print ''.$langs->trans("AntiVirusParam").'
'; print ''.$langs->trans("AntiVirusParamExample").''; print ''; print ''; -print ''; +print ''; if (defined('MAIN_ANTIVIRUS_PARAM')) { print '
'.$langs->trans("ValueIsForcedBySystem").''; } @@ -223,7 +223,7 @@ print ''.$langs->trans("UploadExtensionRestriction").'
'; print ''.$langs->trans("UploadExtensionRestrictionExemple").''; print ''; print ''; -print ''; +print ''; print ""; print ''; diff --git a/htdocs/admin/system/security.php b/htdocs/admin/system/security.php index 3e374c9d9aa..5e203d08aff 100644 --- a/htdocs/admin/system/security.php +++ b/htdocs/admin/system/security.php @@ -461,6 +461,9 @@ print ''.$langs->trans("MaxNumberOfAttachementOnForms").': '; print(getDolGlobalInt('MAIN_SECURITY_MAX_ATTACHMENT_ON_FORMS', 10) ? img_picto('', 'tick').' ' : '').getDolGlobalInt("MAIN_SECURITY_MAX_ATTACHMENT_ON_FORMS", 10).' '.strtolower($langs->trans("Files")); print '

'; + +// Clear password ? + print ''.$langs->trans("DoNotStoreClearPassword").': '; print !getDolGlobalString('DATABASE_PWD_ENCRYPTED') ? '' : img_picto('', 'tick').' '; print yn(!getDolGlobalString('DATABASE_PWD_ENCRYPTED') ? 0 : 1); @@ -470,6 +473,22 @@ if (!getDolGlobalString('DATABASE_PWD_ENCRYPTED')) { print '
'; print '
'; + +// Mask by default in upload +$umask = getDolGlobalString('MAIN_UMASK'); + +print ''.$langs->trans("UMask").': '; +if (! in_array($umask, array('600', '660', '0600', '0660'))) { + print img_warning().' '; +} +print $umask; +if (! in_array($umask, array('600', '660', '0600', '0660'))) { + print '   ('.$langs->trans("Recommended").': 0600 | 0660)'; +} +print '
'; +print '
'; + + /* Already into section conf file */ /* $usepassinconfencrypted = 0; @@ -516,20 +535,16 @@ if (!getDolGlobalString('MAIN_ANTIVIRUS_COMMAND')) { print '
'; print '
'; -$umask = getDolGlobalString('MAIN_UMASK'); +// File extension locked in upload by default -print ''.$langs->trans("UMask").': '; -if (! in_array($umask, array('600', '660', '0600', '0660'))) { - print img_warning().' '; -} -print $umask; -if (! in_array($umask, array('600', '660', '0600', '0660'))) { - print '   ('.$langs->trans("Recommended").': 0600 | 0660)'; -} +print ''.$langs->trans("UploadExtensionRestriction").': '; +print implode(', ', explode(',', getDolGlobalString('MAIN_FILE_EXTENSION_UPLOAD_RESTRICTION'))); +print '   ('.$langs->trans("Recommended").': '.implode(', ', getExecutableContent()).')'; print '
'; print '
'; + $securityevent = new Events($db); $eventstolog = $securityevent->eventstolog; @@ -602,7 +617,6 @@ if (!$test) { } print '
'; - // Modules for Payments $test = isModEnabled('stripe'); if ($test) { @@ -664,6 +678,8 @@ print '
'; print '
'; +// Other setup + print load_fiche_titre($langs->trans("OtherSetup"), '', 'folder'); print '
'; @@ -681,11 +697,9 @@ print 'MAIN_SECURITY_CSRF_WITH_TOKEN = '.getDolGlobalString('MA print '
'; - print '
'; print '
'; - print load_fiche_titre($langs->trans("DatabaseEncryption"), '', 'folder'); print '
'; @@ -734,51 +748,59 @@ print '
'; print '
'; print '
'; + // Websites -print load_fiche_titre($langs->trans("Website"), '', 'website'); -print '
'; +if (isModEnabled('website')) { + print load_fiche_titre($langs->trans("Website"), '', 'website'); + print '
'; -$sql = "SELECT w.rowid as id, w.ref"; -$sql .= " FROM ".MAIN_DB_PREFIX."website as w"; -$sql .= " WHERE w.entity = ".((int) $conf->entity); -$sql .= " AND w.status = 1"; + $sql = "SELECT w.rowid as id, w.ref"; + $sql .= " FROM ".MAIN_DB_PREFIX."website as w"; + $sql .= " WHERE w.entity = ".((int) $conf->entity); + $sql .= " AND w.status = 1"; -$resql = $db->query($sql); -if ($resql) { - $num_rows = $db->num_rows($resql); - if ($num_rows > 0) { - $i = 0; - while ($obj = $db->fetch_object($resql)) { - print "".$langs->trans("RefWebsite").": ".$obj->ref.""; - print'

'; - print 'WEBSITE_'.$obj->id.'_SECURITY_FORCERP = '.getDolGlobalString('WEBSITE_'.$obj->id.'_SECURITY_FORCERP', ''.$langs->trans("Undefined").''); - print '   ('.$langs->trans("Example").': "'; - $examplecsprule = "default-src 'self' 'unsafe-inline' matomo.".getDomainFromURL($_SERVER["SERVER_NAME"], 1)." *.transifex.net *.transifex.com *.cloudflare.com *.cloudflareinsights.com *.google-analytics.com *.googletagmanager.com *.google.com *.gstatic.com *.googleapis.com *.googleadservices.com *.ads-twitter.com *.doubleclick.net; frame-ancestors 'self'; object-src *.youtube.com; frame-src 'self' *.twitter.com *.facebook.com *.youtube.com; img-src * data:;"; - print $examplecsprule; - print '")
'; + $resql = $db->query($sql); + if ($resql) { + $num_rows = $db->num_rows($resql); + if ($num_rows > 0) { + $i = 0; + while ($obj = $db->fetch_object($resql)) { + print "".$langs->trans("RefWebsite").": ".$obj->ref.""; + print'

'; + print 'WEBSITE_'.$obj->id.'_SECURITY_FORCERP = '.getDolGlobalString('WEBSITE_'.$obj->id.'_SECURITY_FORCERP', ''.$langs->trans("Undefined").''); + print '   ('.$langs->trans("Example").': "'; + $examplecsprule = "default-src 'self' 'unsafe-inline' matomo.".getDomainFromURL($_SERVER["SERVER_NAME"], 1)." *.transifex.net *.transifex.com *.cloudflare.com *.cloudflareinsights.com *.google-analytics.com *.googletagmanager.com *.google.com *.gstatic.com *.googleapis.com *.googleadservices.com *.ads-twitter.com *.doubleclick.net; frame-ancestors 'self'; object-src *.youtube.com; frame-src 'self' *.twitter.com *.facebook.com *.youtube.com; img-src * data:;"; + print $examplecsprule; + print '")
'; - print 'WEBSITE_'.$obj->id.'_SECURITY_FORCECSP = '.getDolGlobalString('WEBSITE_'.$obj->id.'_SECURITY_FORCECSP', ''.$langs->trans("Undefined").''); - print '   ('.$langs->trans("Example").': "'; - $examplecsprule = "default-src 'self' 'unsafe-inline' matomo.".getDomainFromURL($_SERVER["SERVER_NAME"], 1)." *.transifex.net *.transifex.com *.cloudflare.com *.cloudflareinsights.com *.google-analytics.com *.googletagmanager.com *.google.com *.gstatic.com *.googleapis.com *.googleadservices.com *.ads-twitter.com *.doubleclick.net; frame-ancestors 'self'; object-src *.youtube.com; frame-src 'self' *.twitter.com *.facebook.com *.youtube.com; img-src * data:;"; - print $examplecsprule; - print '")
'; + print 'WEBSITE_'.$obj->id.'_SECURITY_FORCECSP = '.getDolGlobalString('WEBSITE_'.$obj->id.'_SECURITY_FORCECSP', ''.$langs->trans("Undefined").''); + print '   ('.$langs->trans("Example").': "'; + $examplecsprule = "default-src 'self' 'unsafe-inline' matomo.".getDomainFromURL($_SERVER["SERVER_NAME"], 1)." *.transifex.net *.transifex.com *.cloudflare.com *.cloudflareinsights.com *.google-analytics.com *.googletagmanager.com *.google.com *.gstatic.com *.googleapis.com *.googleadservices.com *.ads-twitter.com *.doubleclick.net; frame-ancestors 'self'; object-src *.youtube.com; frame-src 'self' *.twitter.com *.facebook.com *.youtube.com; img-src * data:;"; + print $examplecsprule; + print '")
'; - print 'WEBSITE_'.$obj->id.'_SECURITY_FORCERP = '.getDolGlobalString('WEBSITE_'.$obj->id.'_SECURITY_FORCERP', ''.$langs->trans("Undefined").'').'   ('.$langs->trans("Recommended").': '.$langs->trans("Undefined").'="strict-origin-when-cross-origin" '.$langs->trans("or").' "same-origin"=more secured)
'; + print 'WEBSITE_'.$obj->id.'_SECURITY_FORCERP = '.getDolGlobalString('WEBSITE_'.$obj->id.'_SECURITY_FORCERP', ''.$langs->trans("Undefined").'').'   ('.$langs->trans("Recommended").': '.$langs->trans("Undefined").'="strict-origin-when-cross-origin" '.$langs->trans("or").' "same-origin"=more secured)
'; - print 'WEBSITE_'.$obj->id.'_SECURITY_FORCESTS = '.getDolGlobalString('WEBSITE_'.$obj->id.'_SECURITY_FORCESTS', ''.$langs->trans("Undefined").'').'   ('.$langs->trans("Example").": \"max-age=31536000; includeSubDomains\")
"; + print 'WEBSITE_'.$obj->id.'_SECURITY_FORCESTS = '.getDolGlobalString('WEBSITE_'.$obj->id.'_SECURITY_FORCESTS', ''.$langs->trans("Undefined").'').'   ('.$langs->trans("Example").": \"max-age=31536000; includeSubDomains\")
"; - print 'WEBSITE_'.$obj->id.'_SECURITY_FORCEPP = '.getDolGlobalString('WEBSITE_'.$obj->id.'_SECURITY_FORCEPP', ''.$langs->trans("Undefined").'').'   ('.$langs->trans("Example").": \"camera=(), microphone=(), geolocation=*\")
"; - $i++; - if ($i != $num_rows) { - print '
'; + print 'WEBSITE_'.$obj->id.'_SECURITY_FORCEPP = '.getDolGlobalString('WEBSITE_'.$obj->id.'_SECURITY_FORCEPP', ''.$langs->trans("Undefined").'').'   ('.$langs->trans("Example").": \"camera=(), microphone=(), geolocation=*\")
"; + $i++; + if ($i != $num_rows) { + print '
'; + } } + } else { + print ''.$langs->trans("NoWebsite").''; } + } else { + dol_print_error($db); } -} else { - dol_print_error($db); + print '
'; + + + print '
'; } -print '
'; // Other - experimental @@ -790,7 +812,7 @@ print 'MAIN_EXEC_USE_POPEN = '; if (!getDolGlobalString('MAIN_EXEC_USE_POPEN')) { print ''.$langs->trans("Undefined").''; } else { - print $conf->global->MAIN_EXEC_USE_POPEN; + print getDolGlobalString('MAIN_EXEC_USE_POPEN'); } if ($execmethod == 1) { print '     "exec" PHP method will be used for shell commands'; @@ -869,6 +891,11 @@ print '
'; print 'MAIN_ALLOW_SVG_FILES_AS_EXTERNAL_LINKS = '.getDolGlobalString('MAIN_ALLOW_SVG_FILES_AS_EXTERNAL_LINKS', ''.$langs->trans("Undefined").'   ('.$langs->trans("Recommended").': '.$langs->trans("Undefined").' '.$langs->trans("or").' 0)')."
"; print '
'; +print 'MAIN_DISALLOW_STRING_OBFUSCATION_IN_DOL_EVAL = '.(getDolGlobalString('MAIN_DISALLOW_STRING_OBFUSCATION_IN_DOL_EVAL') ? '1' : ''.$langs->trans("Undefined").''); +print '   ('.$langs->trans("Recommended").": 1 - may break use of concatenation function like . or dol_concatdesc into extra fields conditions or formula)
"; +print '
'; + + // MAIN_ALLOW_LOCAL_LINKS_AS_EXTERNAL_LINKS print 'MAIN_SECURITY_CSRF_TOKEN_RENEWAL_ON_EACH_CALL = '.getDolGlobalString('MAIN_SECURITY_CSRF_TOKEN_RENEWAL_ON_EACH_CALL', ''.$langs->trans("Undefined").'   ('.$langs->trans("Recommended").': '.$langs->trans("Undefined").' '.$langs->trans("or").' 0)')."
"; @@ -889,9 +916,11 @@ print 'MAIN_SECURITY_FORCERP = '.getDolGlobalString('MAIN_SECUR print '
'; print 'MAIN_SECURITY_FORCE_ACCESS_CONTROL_ALLOW_ORIGIN = '.getDolGlobalString('MAIN_SECURITY_FORCE_ACCESS_CONTROL_ALLOW_ORIGIN', ''.$langs->trans("Undefined").'').'   ('.$langs->trans("Recommended").": 1)
"; -print '
'; +/* Removed, already in the dedicated section Websites. +print '
'; + print 'WEBSITE_MAIN_SECURITY_FORCECSPRO = '.getDolGlobalString('WEBSITE_MAIN_SECURITY_FORCECSPRO', ''.$langs->trans("Undefined").''); print '   ('.$langs->trans("Example").': "'; $examplecsprule = "default-src 'self' 'unsafe-inline' matomo.".getDomainFromURL($_SERVER["SERVER_NAME"], 1)." *.transifex.net *.transifex.com *.cloudflare.com *.cloudflareinsights.com *.google-analytics.com *.googletagmanager.com *.google.com *.gstatic.com *.googleapis.com *.googleadservices.com *.ads-twitter.com *.doubleclick.net; frame-ancestors 'self'; object-src *.youtube.com; frame-src 'self' *.twitter.com *.facebook.com *.youtube.com; img-src * data:;"; @@ -913,10 +942,12 @@ print 'WEBSITE_MAIN_SECURITY_FORCESTS = '.getDolGlobalString('W print '
'; print 'WEBSITE_MAIN_SECURITY_FORCEPP = '.getDolGlobalString('WEBSITE_MAIN_SECURITY_FORCEPP', ''.$langs->trans("Undefined").'').'   ('.$langs->trans("Example").": \"camera=(), microphone=(), geolocation=*\")
"; +*/ print ''; +print '
'; print '
'; diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index 1a71d9d6c55..bf0652760f4 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -1972,11 +1972,13 @@ function dol_add_file_process($upload_dir, $allowoverwrite = 0, $updatesessionor $info = pathinfo($destfile); $destfile = dol_sanitizeFileName($info['filename'].($info['extension'] != '' ? ('.'.strtolower($info['extension'])) : '')); - $fileextensionrestriction = getDolGlobalString("MAIN_FILE_EXTENSION_UPLOAD_RESTRICTION", 'htm,html,shtml,js,php'); - if (!empty($info['extension']) && !empty($fileextensionrestriction)) { - $fileextensionrestrictionarr = explode(",", $fileextensionrestriction); - foreach ($fileextensionrestrictionarr as $key => $fileextension) { - if (preg_match('/'.preg_quote($fileextension, '/').'/i', $info['extension'])) { + // Check extension is allowed for upload + $fileextensionrestriction = getDolGlobalString("MAIN_FILE_EXTENSION_UPLOAD_RESTRICTION", implode(',', getExecutableContent())); + if (!empty($fileextensionrestriction)) { + $arrayofregexextension = explode(",", $fileextensionrestriction); + + foreach ($arrayofregexextension as $fileextension) { + if (preg_match('/\.'.preg_quote(trim($fileextension), '/').'$/i', $destfull)) { $langs->load("errors"); // key must be loaded because we can't rely on loading during output, we need var substitution to be done now. setEventMessages($langs->trans("ErrorFilenameExtensionNotAllowed", $filenameto), null, 'errors'); return -1; diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index d966af8305c..ae2f9eb3a4f 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -14118,16 +14118,35 @@ function fetchObjectByElement($element_id, $element_type, $element_ref = '', $us return $ret; } +/** + * Return array of extension for executable files of text files that can contains executable code. + * + * @return array Array of extensions + */ +function getExecutableContent() +{ + $arrayofregexextension = array( + 'htm', 'html', 'shtml', 'js', 'phar', 'php', 'php3', 'php4', 'php5', 'phtml', 'pht', 'pl', 'py', 'cgi', 'ksh', 'sh', 'shtml', + 'bash', 'bat', 'cmd', 'wpk', 'exe', 'dmg', 'appimage' + ); + + return $arrayofregexextension; +} + /** * Return if a file can contains executable content * - * @param string $filename File name to test - * @return boolean True if yes, False if no + * @param string $filename File name to test + * @return boolean True if yes, False if no */ function isAFileWithExecutableContent($filename) { - if (preg_match('/\.(htm|html|js|phar|php|php\d+|phtml|pht|pl|py|cgi|ksh|sh|shtml|bash|bat|cmd|wpk|exe|dmg)$/i', $filename)) { - return true; + $arrayofregexextension = getExecutableContent(); + + foreach ($arrayofregexextension as $fileextension) { + if (preg_match('/\.'.preg_quote($fileextension, '/').'$/i', $filename)) { + return true; + } } return false;