CVE-2023-47123: Insufficient Information (NVD-CWE-noinfo)
value: iTop is an IT service management platform.  By filling malicious code in an object friendlyname / complementary name, an XSS attack can be performed when this object will displayed as an n:n relation item in another object. This vulnerability is fixed in 3.1.1 and 3.2.0.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
Published: 2024-04-15T18:15Z
Repository: https://github.com/Combodo/iTop
Language: PHP
Files changed: sources/Service/Base/ObjectRepository.php
Commit date: 2023-11-09 16:43:37 +0100
Commit message: N°6917 - Security hardening

Diff: diff --git a/sources/Service/Base/ObjectRepository.php b/sources/Service/Base/ObjectRepository.php
index f8ada588a58..77eac98e57d 100644
--- a/sources/Service/Base/ObjectRepository.php
+++ b/sources/Service/Base/ObjectRepository.php
@@ -36,11 +36,11 @@ class ObjectRepository
 	 * @param array $aFieldsToLoad Additional fields to load
 	 * @param string $sSearch Friendly name search string
 	 *
 	 * @return array|null
 	 */
-	static public function Search(string $sObjectClass, array $aFieldsToLoad, string $sSearch): ?array
+	public static function Search(string $sObjectClass, array $aFieldsToLoad, string $sSearch): ?array
 	{
 		try {
 
 			// Create db search
 			$oDbObjectSearch = new DBObjectSearch($sObjectClass);
@@ -80,11 +80,11 @@ class ObjectRepository
 	 * @param string $sSearch Friendly name search string
 	 * @param DBObject|null $oThisObject This object reference for oql
 	 *
 	 * @return array|null
 	 */
-	static public function SearchFromOql(string $sObjectClass, array $aFieldsToLoad, string $sOql, string $sSearch, DBObject $oThisObject = null): ?array
+	public static function SearchFromOql(string $sObjectClass, array $aFieldsToLoad, string $sOql, string $sSearch, DBObject $oThisObject = null): ?array
 	{
 		try {
 
 			// Create db search
 			$oDbObjectSearch = DBSearch::FromOQL($sOql);
@@ -115,11 +115,11 @@ class ObjectRepository
 	 * @return array
 	 * @throws \ArchivedObjectException
 	 * @throws \CoreException
 	 * @throws \DictExceptionMissingString
 	 */
-	static private function DBSetToObjectArray(iDBObjectSetIterator $oDbObjectSet, string $sObjectClass, array $aFieldsToLoad): array
+	private static function DBSetToObjectArray(iDBObjectSetIterator $oDbObjectSet, string $sObjectClass, array $aFieldsToLoad): array
 	{
 		// Retrieve friendly name complementary specification
 		$aComplementAttributeSpec = MetaModel::GetNameSpec($sObjectClass, FriendlyNameType::COMPLEMENTARY);
 
 		// Retrieve image attribute code
@@ -156,11 +156,11 @@ class ObjectRepository
 	 * @param array $aComplementAttributeSpec Friendly name complementary spec
 	 * @param string $sObjectImageAttCode Image attribute code
 	 *
 	 * @return mixed
 	 */
-	static public function GetDefaultFieldsToLoad(array $aComplementAttributeSpec, string $sObjectImageAttCode)
+	public static function GetDefaultFieldsToLoad(array $aComplementAttributeSpec, string $sObjectImageAttCode)
 	{
 		// Friendly name complementary fields
 		$aFieldsToLoad = $aComplementAttributeSpec[1];
 
 		// Image attribute
@@ -183,31 +183,33 @@ class ObjectRepository
 	 * @param array $aComplementAttributeSpec Friendly name complementary spec
 	 * @param string $sObjectImageAttCode Image attribute code
 	 *
 	 * @return array
 	 */
-	static public function ComputeOthersData(DBObject $oDbObject, string $sClass, array $aData, array $aComplementAttributeSpec, string $sObjectImageAttCode): array
+	public static function ComputeOthersData(DBObject $oDbObject, string $sClass, array $aData, array $aComplementAttributeSpec, string $sObjectImageAttCode): array
 	{
 		try {
 
 			// object class
 			$aData['class_name'] = get_class($oDbObject);
 
 			// Obsolescence flag
 			$aData['obsolescence_flag'] = $oDbObject->IsObsolete();
 
 			// Additional fields
+			$sFriendlynameForHtml = utils::EscapeHtml($aData['friendlyname']);
 			if (count($aComplementAttributeSpec[1]) > 0) {
 				$aData['has_additional_field'] = true;
 				$aArguments = [];
 				foreach ($aComplementAttributeSpec[1] as $sAdditionalField) {
 					$aArguments[] = $oDbObject->Get($sAdditionalField);
 				}
 				$aData['additional_field'] = vsprintf($aComplementAttributeSpec[0], $aArguments);
-				$aData['full_description'] = "{$aData['friendlyname']}<br><i><small>{$aData['additional_field']}</small></i>";
+				$sAdditionalFieldForHtml = utils::EscapeHtml($aData['additional_field']);
+				$aData['full_description'] = "{$sFriendlynameForHtml}<br><i><small>{$sAdditionalFieldForHtml}</small></i>";
 			} else {
-				$aData['full_description'] = $aData['friendlyname'];
+				$aData['full_description'] = $sFriendlynameForHtml;
 			}
 
 			// Image
 			if (!empty($sObjectImageAttCode)) {
 				$aData['has_image'] = true;
@@ -306,11 +308,11 @@ class ObjectRepository
 	 *
 	 * @param string $sOql OQL expression
 	 *
 	 * @return bool
 	 */
-	static public function DeleteFromOql(string $sOql): bool
+	public static function DeleteFromOql(string $sOql): bool
 	{
 		try {
 
 			// Create db search
 			$oDbObjectSearch = DBSearch::FromOQL($sOql);

Vulnerable code: 	static public function Search(string $sObjectClass, array $aFieldsToLoad, string $sSearch): ?array
	static public function SearchFromOql(string $sObjectClass, array $aFieldsToLoad, string $sOql, string $sSearch, DBObject $oThisObject = null): ?array
	static private function DBSetToObjectArray(iDBObjectSetIterator $oDbObjectSet, string $sObjectClass, array $aFieldsToLoad): array
	static public function GetDefaultFieldsToLoad(array $aComplementAttributeSpec, string $sObjectImageAttCode)
	static public function ComputeOthersData(DBObject $oDbObject, string $sClass, array $aData, array $aComplementAttributeSpec, string $sObjectImageAttCode): array
				$aData['full_description'] = "{$aData['friendlyname']}<br><i><small>{$aData['additional_field']}</small></i>";
				$aData['full_description'] = $aData['friendlyname'];
	static public function DeleteFromOql(string $sOql): bool
Fixed code: 	public static function Search(string $sObjectClass, array $aFieldsToLoad, string $sSearch): ?array
	public static function SearchFromOql(string $sObjectClass, array $aFieldsToLoad, string $sOql, string $sSearch, DBObject $oThisObject = null): ?array
	private static function DBSetToObjectArray(iDBObjectSetIterator $oDbObjectSet, string $sObjectClass, array $aFieldsToLoad): array
	public static function GetDefaultFieldsToLoad(array $aComplementAttributeSpec, string $sObjectImageAttCode)
	public static function ComputeOthersData(DBObject $oDbObject, string $sClass, array $aData, array $aComplementAttributeSpec, string $sObjectImageAttCode): array
			$sFriendlynameForHtml = utils::EscapeHtml($aData['friendlyname']);
				$sAdditionalFieldForHtml = utils::EscapeHtml($aData['additional_field']);
				$aData['full_description'] = "{$sFriendlynameForHtml}<br><i><small>{$sAdditionalFieldForHtml}</small></i>";
				$aData['full_description'] = $sFriendlynameForHtml;
	public static function DeleteFromOql(string $sOql): bool