From 0844ed2f9bee21b722dcd7446ac1ae698cbec4cc Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 19 Oct 2024 13:16:13 +0200 Subject: [PATCH] NEW Include a protection into check update to detect malware --- htdocs/admin/modules.php | 16 ++++-- htdocs/core/modules/DolibarrModules.class.php | 49 +++++++++++++++++++ htdocs/langs/en_US/errors.lang | 2 + 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/htdocs/admin/modules.php b/htdocs/admin/modules.php index 8e0a8bb66ce..e8c2a7a925d 100644 --- a/htdocs/admin/modules.php +++ b/htdocs/admin/modules.php @@ -1,7 +1,7 @@ * Copyright (C) 2003 Jean-Louis Bergamo - * Copyright (C) 2004-2017 Laurent Destailleur + * Copyright (C) 2004-2024 Laurent Destailleur * Copyright (C) 2004 Eric Seigne * Copyright (C) 2005-2017 Regis Houssin * Copyright (C) 2011-2023 Juanjo Menent @@ -837,11 +837,21 @@ if ($mode == 'common' || $mode == 'commonkanban') { || getDolGlobalString('CHECKLASTVERSION_EXTERNALMODULE') ) ) { - $checkRes = $objMod->checkForUpdate(); + $checkRes = $objMod->checkForUpdate(); // Check for update version if ($checkRes > 0) { setEventMessage($objMod->getName().' : '.$versiontrans.' -> '.$objMod->lastVersion); } elseif ($checkRes < 0) { - setEventMessage($objMod->getName().' '.$langs->trans('CheckVersionFail'), 'warnings'); + setEventMessage($objMod->getName().': '.$langs->trans('CheckVersionFail'), 'warnings'); + } + } + + if ($objMod->isCoreOrExternalModule() == 'external' && !getDolGlobalString('DISABLE_CHECK_ON_MALWARE_MODULES')) { + $checkRes = $objMod->checkForCompliance(); // Check if module is reported as non compliant with Dolibarr rules and law + if (!is_numeric($checkRes) && $checkRes != '') { + $langs->load("errors"); + var_dump($checkRes); + var_dump($langs->trans($checkRes)); + setEventMessages($objMod->getName().' : '.$langs->trans($checkRes), null, 'errors'); } } diff --git a/htdocs/core/modules/DolibarrModules.class.php b/htdocs/core/modules/DolibarrModules.class.php index 1f300718385..e46375262bd 100644 --- a/htdocs/core/modules/DolibarrModules.class.php +++ b/htdocs/core/modules/DolibarrModules.class.php @@ -2529,4 +2529,53 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it } return 0; } + + /** + * Check for module compliance with Dolibarr rules and law + * If a module is reported by this function,it is surely a malware. Delete it as soon as possible. + * + * @return int|string Return integer <0 if Error, 0 == not compliant, 'string' with message if module not compliant + */ + public function checkForCompliance() + { + global $conf, $langs; + + // Get list of illegal modules name or ID + if (empty($conf->cache['noncompliantmodules'])) { + require_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php'; + + $urlforblacklistmodules = 'www.dolibarr.org/_service_noncompliantmodules.php'; + + $result = getURLContent($urlforblacklistmodules, 'GET', '', 1, array(), array('http', 'https'), 0); // Accept http or https links on external remote server only + if (isset($result['content']) && $result['http_code'] == 200) { + $langs->load("errors"); + + // Security warning : be careful with remote data content, the module editor could be hacked (or evil) so limit to a-z A-Z 0-9 _ . - + $arrayoflines = preg_split("/[\n,]/", $result['content']); + foreach ($arrayoflines as $line) { + $tmpfieldsofline = explode(';', $line); + $modulekey = strtolower($tmpfieldsofline[0]); + $conf->cache['noncompliantmodules'][$modulekey]['name'] = $tmpfieldsofline[0]; + $conf->cache['noncompliantmodules'][$modulekey]['id'] = $tmpfieldsofline[1]; + $conf->cache['noncompliantmodules'][$modulekey]['message'] = $langs->trans(empty($tmpfieldsofline[2]) ? 'WarningModuleAffiliatedToAReportedCompany' : $tmpfieldsofline[2]); + if (!empty($tmpfieldsofline[3])) { + $conf->cache['noncompliantmodules'][$modulekey]['message2'] = $langs->trans("WarningModuleAffiliatedToAPiratPlatform", $tmpfieldsofline[3]); + } + } + } + } + + if (!empty($conf->cache['noncompliantmodules'])) { + $modulekey = strtolower($this->name); + if (in_array($modulekey, array_keys($conf->cache['noncompliantmodules']))) { + $answer = trim($conf->cache['noncompliantmodules'][$modulekey]['message']); + if (!empty($conf->cache['noncompliantmodules'][$modulekey]['message2'])) { + $answer .= '
'.$conf->cache['noncompliantmodules'][$modulekey]['message2']; + } + return $answer; + } + } + + return 0; + } } diff --git a/htdocs/langs/en_US/errors.lang b/htdocs/langs/en_US/errors.lang index 29558bfd042..35e3c6cccb1 100644 --- a/htdocs/langs/en_US/errors.lang +++ b/htdocs/langs/en_US/errors.lang @@ -377,6 +377,8 @@ WarningGoOnAccountancySetupToAddAccounts=If this list is empty, go into menu %s WarningCorrectedInvoiceNotFound=Corrected invoice not found WarningCommentNotFound=Please check placement of start and end comments for %s section in file %s before submitting your action WarningAlreadyReverse=Stock movement already reversed +WarningModuleAffiliatedToAReportedCompany=Warning, this module has been reported to the Dolibar foundation as being published by a company using illegal practices (non-compliance with the rules for using the Dolibarr brand, collecting your data without your consent or deploying malware). Use it at your own risk! +WarningModuleAffiliatedToAPiratPlatform=Be careful to never get a module (paid or free) from a pirate platform like %s SwissQrOnlyVIR = SwissQR invoice can only be added on invoices set to be paid with credit transfer payments. SwissQrCreditorAddressInvalid = Creditor address is invalid (are ZIP and city set? (%s)