Lors du traitement des fichiers XML dans PHP, xml_set_external_entity_ref_handler et libxml_disable_entity_loadher sont deux fonctions couramment utilisées, qui sont utilisées pour gérer respectivement les entités externes et désactiver le chargement externe, respectivement. Cependant, l'utilisation des deux peut entraîner des problèmes de compatibilité, en particulier lorsqu'il s'agit de XML impliquant des DTD externes (définitions de type de documents) et des entités. Cet article explorera les causes profondes de ces problèmes et fournira des solutions.
xml_set_external_entity_ref_handler est une fonction PHP qui vous permet de spécifier une fonction de rappel personnalisée pour gérer les références aux entités externes dans des documents XML. Les entités externes sont souvent utilisées pour introduire des ressources externes dans des documents XML, tels que les fichiers DTD, d'autres fichiers XML ou des fichiers texte.
Lors de l'analyse d'un document XML avec une référence d'entité externe, XML_SET_EXTERNAL_ENTITY_REF_HANDLER appelle la fonction de rappel que vous définissez, vous permettant de personnaliser la logique de traitement avant l'analyse de l'entité.
libxml_disable_entity_loadher est une autre fonction PHP qui désactive l'analyseur XML pour charger des entités externes. Cette fonction est généralement utilisée pour empêcher les attaques d'injection de l'entité externe XML (attaques XXE). En désactivant le chargement des entités externes, vous pouvez vous assurer que l'analyseur XML ne charge pas accidentellement des informations sensibles à partir de ressources externes.
Les fonctions de ces deux fonctions semblent sans importance, mais elles peuvent être confrontées. xml_set_external_entity_ref_handler s'attend à pouvoir gérer le chargement d'entités externes, tandis que libxml_disable_entity_loader désactive le chargement des entités externes. Lorsque le chargement de l'entité est désactivé, la fonction de rappel de xml_set_external_entity_ref_handler ne peut pas être déclenchée car l'analyseur XML n'essaie pas de charger des entités externes.
Cela conduit à des problèmes de compatibilité entre les deux. Si vous souhaitez toujours utiliser XML_SET_EXTERNAL_ENTITY_REF_HANDLER pour gérer les références d'entités externes après le chargement de l'entité désactivée, vous devez prendre des mesures spéciales.
Pour s'assurer que XML_SET_EXTERNAL_ENTITY_REF_HANDLER est compatible avec libxml_disable_entity_loadher , vous pouvez prendre les méthodes suivantes:
La pratique la plus courante consiste à désactiver le chargement des entités externes pour empêcher les attaques XXE, mais aussi utiliser XML_SET_EXTERNAL_ENTITY_REF_HANDLER pour gérer des références d'entités externes spécifiques. Pour y parvenir, vous pouvez utiliser le code suivant:
<span><span><span class="hljs-comment">// Désactiver le chargement des entités externes</span></span><span>
</span><span><span class="hljs-title function_ invoke__">libxml_disable_entity_loader</span></span><span>(</span><span><span class="hljs-literal">true</span></span><span>);
</span><span><span class="hljs-comment">// Configuration de la fonction de traitement de référence de l'entité externe</span></span><span>
</span><span><span class="hljs-title function_ invoke__">xml_set_external_entity_ref_handler</span></span><span>(function (</span><span><span class="hljs-variable">$entity</span></span><span>, </span><span><span class="hljs-variable">$system</span></span><span>, </span><span><span class="hljs-variable">$public</span></span><span>) {
</span><span><span class="hljs-comment">// Gérer les références d'entités externes</span></span><span>
</span><span><span class="hljs-comment">// Par exemple, le chargement des entités à partir de fichiers locaux ou de bases de données</span></span><span>
</span><span><span class="hljs-keyword">return</span></span><span> </span><span><span class="hljs-string">'/path/to/your/local/entity'</span></span><span>;
});
</span><span><span class="hljs-comment">// Analyse XML</span></span><span>
</span><span><span class="hljs-variable">$xml</span></span><span> = </span><span><span class="hljs-title function_ invoke__">simplexml_load_file</span></span><span>(</span><span><span class="hljs-string">'yourfile.xml'</span></span><span>);
</span></span>
De cette façon, libxml_disable_entity_loader désactive le chargement de toutes les entités externes, tandis que XML_SET_EXTERNAL_ENTITY_REF_HANDLER peut être utilisée pour personnaliser le traitement lorsqu'une entité externe spécifique est rencontrée.
Si vous devez autoriser le chargement des entités externes dans certaines situations, le chargement des entités peut être activé temporairement pendant une phase de traitement spécifique. Vous pouvez explicitement activer ou désactiver le chargement des entités avant et après l'analyse du XML:
<span><span><span class="hljs-comment">// Désactiver le chargement des entités externes</span></span><span>
</span><span><span class="hljs-title function_ invoke__">libxml_disable_entity_loader</span></span><span>(</span><span><span class="hljs-literal">true</span></span><span>);
</span><span><span class="hljs-comment">// Analyse XML</span></span><span>
</span><span><span class="hljs-variable">$xml</span></span><span> = </span><span><span class="hljs-title function_ invoke__">simplexml_load_file</span></span><span>(</span><span><span class="hljs-string">'yourfile.xml'</span></span><span>);
</span><span><span class="hljs-comment">// Permettez aux entités externes de se charger à un moment précis</span></span><span>
</span><span><span class="hljs-title function_ invoke__">libxml_disable_entity_loader</span></span><span>(</span><span><span class="hljs-literal">false</span></span><span>);
</span><span><span class="hljs-comment">// Continuer avec d'autres opérations</span></span><span>
</span></span>
Cette approche permet un contrôle plus granulaire lorsque les entités externes sont chargées, en évitant les problèmes de sécurité tout en permettant une analyse XML flexible.
Si vous ne souhaitez pas désactiver le chargement des entités externes mais que vous souhaitez toujours éviter les problèmes de sécurité, vous pouvez implémenter des vérifications de sécurité dans la fonction de rappel XML_SET_EXTERNAL_ENTITY_REF_HANDLER . Par exemple, vous pouvez vérifier si l'URI d'une entité externe est digne de confiance ou autoriser uniquement les fichiers locaux à charger:
<span><span><span class="hljs-comment">// Configuration de la fonction de traitement de référence de l'entité externe</span></span><span>
</span><span><span class="hljs-title function_ invoke__">xml_set_external_entity_ref_handler</span></span><span>(function (</span><span><span class="hljs-variable">$entity</span></span><span>, </span><span><span class="hljs-variable">$system</span></span><span>, </span><span><span class="hljs-variable">$public</span></span><span>) {
</span><span><span class="hljs-comment">// Effectuer des inspections de sécurité,Assurez-vous que les entités non fiables ne sont pas chargées</span></span><span>
</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-title function_ invoke__">strpos</span></span><span>(</span><span><span class="hljs-variable">$system</span></span><span>, </span><span><span class="hljs-string">'trusted-path'</span></span><span>) === </span><span><span class="hljs-literal">false</span></span><span>) {
</span><span><span class="hljs-keyword">return</span></span><span> </span><span><span class="hljs-string">''</span></span><span>; </span><span><span class="hljs-comment">// Renvoie une chaîne vide pour indiquer que l'entité n'est pas chargée</span></span><span>
}
</span><span><span class="hljs-comment">// Gérer les entités externes de confiance</span></span><span>
</span><span><span class="hljs-keyword">return</span></span><span> </span><span><span class="hljs-string">'/path/to/your/trusted/entity'</span></span><span>;
});
</span><span><span class="hljs-comment">// Analyse XML</span></span><span>
</span><span><span class="hljs-variable">$xml</span></span><span> = </span><span><span class="hljs-title function_ invoke__">simplexml_load_file</span></span><span>(</span><span><span class="hljs-string">'yourfile.xml'</span></span><span>);
</span></span>
Cette approche vous permet de contrôler les entités qui peuvent être chargées tout en permettant aux entités externes de se charger, évitant ainsi les risques de sécurité potentiels.
Dans PHP, les deux fonctions XML_SET_EXTERNAL_ENTITY_REF_HANDLER et LIBXML_DISABLE_ENTITY_LOADER ont des objectifs différents, mais il peut y avoir des conflits entre eux. Grâce à une configuration raisonnable et à un ajustement de code, vous pouvez vous assurer que ces deux fonctions peuvent être compatibles, en répondant aux besoins du traitement de référence des entités externes et en évitant les risques de sécurité apportés par le chargement externe des entités. Le choix de la bonne solution dépend de vos besoins spécifiques et de vos exigences de sécurité.