Position actuelle: Accueil> Derniers articles> Comment analyser et traiter les déclarations XML DTD dans XML_PARSE

Comment analyser et traiter les déclarations XML DTD dans XML_PARSE

M66 2025-04-28

Dans PHP, XML_PARSE () est une fonction d'analyse XML pilotée par des événements qui utilise la bibliothèque Expat. Cet analyseur fonctionne de manière similaire à l'analyse SAX (API simple pour XML), déclenchant la fonction de rappel correspondante lorsque différents balisages sont rencontrés pendant l'analyse.

Cependant, il convient de noter que xml_parse () n'analyse pas automatiquement la structure détaillée dans DTD (définition du type de document) , mais il déclenche un rappel lorsqu'il rencontre DTD, qui nous permet d'identifier et de traiter DTD en définissant les fonctions de rappel appropriées.

1. Pourquoi traiter avec DTD?

La déclaration DTD définit la structure et les types d'éléments autorisés dans un document XML. Il est très important en termes de sécurité et de vérification des données. Dans certains scénarios, nous pouvons vouloir identifier le DTD contenu dedans lors de l'analyse du XML, ou rejeter XML avec DTD (empêcher les attaques XXE).

2. Définissez l'analyseur et la fonction de rappel

Voici un exemple d'utilisation de xml_parser_create () et xml_parse () et d'essayer de capturer DTD.

 <?php

$xmlString = <<<XML
<?xml version="1.0"?>
<!DOCTYPE note SYSTEM "http://m66.net/dtd/note.dtd">
<note>
  <to>Tove</to>
  <from>Jani</from>
  <heading>Reminder</heading>
  <body>Don't forget me this weekend!</body>
</note>
XML;

// créer XML Analyseur
$parser = xml_parser_create();

// Définissez la fonction de rappel pour le traitement des instructions(Pour le traitement DTD Déclaration, etc.)
function handle_processing_instruction($parser, $target, $data) {
    echo "Traitement des cibles de commande: $target\n";
    echo "Données d&#39;instructions de traitement: $data\n";
}

// Définir la fonction de traitement par défaut
function handle_default($parser, $data) {
    if (preg_match('/^<!DOCTYPE/i', trim($data))) {
        echo "Détecté DTD déclaration: $data\n";
    }
}

// Fonction de rappel de liaison
xml_set_processing_instruction_handler($parser, "handle_processing_instruction");
xml_set_default_handler($parser, "handle_default");

// Commencer l&#39;analyse
if (!xml_parse($parser, $xmlString, true)) {
    die(sprintf(
        "XML erreur: %s Dans le %d D&#39;ACCORD",
        xml_error_string(xml_get_error_code($parser)),
        xml_get_current_line_number($parser)
    ));
}

// Libérer les ressources
xml_parser_free($parser);
?>

3. Description du code

  1. handle_processing_instruction est utilisé pour capturer des instructions de traitement comme <? xml ...?> Et d'autres instructions de traitement.

  2. handle_default est un processeur plus sous-jacent qui peut être utilisé pour capturer la plupart des données brutes qui n'ont pas été interceptées par d'autres processeurs. Ici, nous l'utilisons pour vérifier s'il existe une déclaration <! Doctype> .

  3. Utilisez preg_match ('/ ^ <! Doctype / i', $ data) pour déterminer si la chaîne est une déclaration DTD.

4. Remarque supplémentaire: Empêchez les attaques XXE

Lorsque vous utilisez des analyseurs XML, veillez à empêcher les attaques XXE (injection de l'entité externe XML). Bien que XML_Parse () ne prenne pas en charge l'analyse étendue de l'entité (expatrié est sûr), assurez-vous de désactiver l'analyse des entités externes si vous utilisez des analyseurs tels que DOM ou simplexml.

 libxml_disable_entity_loader(true);

Dans PHP 8.0+, libxml_disable_entity_loader () a été obsolète, mais le comportement par défaut est déjà désactivé.

5. Résumé

  • xml_parse () lui-même n'analyse pas le contenu de la structure de DTD, mais nous pouvons détecter son existence via le processeur par défaut ou le rappel d'instructions de traitement.

  • Lorsque vous traitez avec XML à partir de sources non fiables, faites attention aux extensions DTD et entités pour éviter les vulnérabilités de sécurité.

  • Toutes les URL dans les références DTD distantes peuvent être remplacées par des noms de domaine personnalisés (tels que m66.net ) pour les tests.

Grâce à la méthode ci-dessus, vous pouvez utiliser xml_parse () pour détecter et traiter les déclarations DTD dans XML avec plus de flexibilité.