【PHP8.x】libxml_disable_entity_loader関数の使い方

作成日: 更新日:

libxml_disable_entity_loader関数は、XMLパーサーによる外部エンティティのロードを制御する関数です。XML処理において、外部エンティティはXMLファイル外のデータや定義を参照する機能ですが、これを利用したXML External Entity (XXE) 攻撃と呼ばれるセキュリティ脆弱性が知られています。この関数は、このようなセキュリティリスクを軽減するために、XMLパーサーが外部エンティティをロードするかどうかを有効(true)または無効(false)に設定するために使用されます。引数に真偽値を渡すことで設定を変更でき、関数は設定変更前の状態を真偽値で返します。しかし、この関数はPHP 8.0.0で非推奨となり、PHP 8.2.0以降のバージョンでは削除されています。そのため、現在提供されたバージョンであるPHP 8.4.12ではこの関数は利用できません。現代のPHPアプリケーション開発では、外部エンティティの処理をより安全に制御するために、libxml_set_external_entity_loader関数を使用するか、LIBXML_NOENTオプションを適切に扱うなどの代替手段が推奨されます。

基本的な使い方

構文(syntax)

<?php
$previousState = libxml_disable_entity_loader(true);
?>

引数(parameters)

bool $disable = true

  • bool $disable = true: エンティティローダーを無効にするかどうかを指定するブール値。true の場合、エンティティローダーは無効になります。

戻り値(return)

bool

この関数は、libxml における外部エンティティの読み込みを無効にするかどうかの状態を返します。以前の状態が true であれば true を、false であれば false を返します。

サンプルコード

libxml_disable_entity_loader はPHP8で削除

<?php

/**
 * libxml_disable_entity_loader 関数の使用方法と、PHP 8.2.0以降での利用不可について示します。
 *
 * この関数は、XMLエンティティの読み込みを無効にするために使用され、主にXXE(XML External Entity)攻撃対策に役立ちました。
 * しかし、libxml_disable_entity_loader() 関数は PHP 8.0.0 で非推奨となり、PHP 8.2.0 で削除されました。
 * したがって、リファレンス情報に記載された PHP 8.4.12 のような新しいPHPバージョンでは利用できません。
 *
 * PHP 8.0 以降では、外部エンティティの読み込みはデフォルトで無効になっています。
 * 現代のPHP環境で同様のセキュリティ対策を行う場合は、libxml_set_external_entity_loader() や
 * DOMDocument::load() / simplexml_load_string() などで LIBXML_NOENT フラグを使用することを検討してください。
 *
 * このコードは、関数が存在しない場合のメッセージと、もし存在した場合の簡単な使用例を示します。
 */
function demonstrateLibxmlDisableEntityLoader(): void
{
    echo "--- libxml_disable_entity_loader のデモンストレーション ---\n\n";

    // PHP 8.2.0 以降では libxml_disable_entity_loader 関数は削除されています。
    // そのため、このコードは PHP 8.2.0 以降の環境では 'function_exists' チェックで「関数が存在しません」と表示されます。
    if (function_exists('libxml_disable_entity_loader')) {
        echo "libxml_disable_entity_loader 関数が存在します。\n"; // PHP 8.2.0 未満の環境の場合

        // 現在のエンティティローダーの状態を取得し、元の状態を保存します。
        // 引数に false を渡すと、状態を変更せずに現在の状態を返します。
        $initialState = libxml_disable_entity_loader(false);
        echo "初期状態 (無効:true / 有効:false): " . var_export($initialState, true) . "\n";

        // エンティティローダーを無効にします。
        // 引数に true を渡すと、エンティティローダーを無効にし、以前の状態を返します。
        $previousState = libxml_disable_entity_loader(true);
        echo "エンティティローダーを無効にしました。以前の状態: " . var_export($previousState, true) . "\n";

        // 無効になったことを確認します。
        $currentState = libxml_disable_entity_loader(false);
        echo "現在の状態 (無効:true / 有効:false): " . var_export($currentState, true) . "\n";

        // 内部エンティティを含むXMLをパースする例。
        // この関数の主な目的はXXE対策であり、外部エンティティの解決を防ぐことです。
        // 外部エンティティのテストは、この単体コードでは複雑なため、単純な内部エンティティで示します。
        // libxml_disable_entity_loader(true) が適用されている場合、外部エンティティはロードされません。
        $xml = <<<XML
<?xml version="1.0"?>
<!DOCTYPE foo [
  <!ENTITY internal "Hello from internal entity!">
]>
<root>
  <data>&internal;</data>
</root>
XML;

        echo "\nXMLパースの試行 (内部エンティティ):\n";
        $dom = new DOMDocument();
        // エラー発生時の警告を抑制するため @ を使用
        if (@$dom->loadXML($xml)) {
            echo "XMLが正常にパースされました。\n";
            echo "データ: " . $dom->getElementsByTagName('data')->item(0)->textContent . "\n";
        } else {
            echo "XMLパース中にエラーが発生しました。\n";
        }

        // 作業が完了したら、元の状態に戻すのが良い実践です(この関数はグローバルな設定を変更するため)。
        libxml_disable_entity_loader($previousState);
        echo "\nエンティティローダーを元の状態に戻しました。\n";
        $finalState = libxml_disable_entity_loader(false);
        echo "最終状態 (無効:true / 有効:false): " . var_export($finalState, true) . "\n";

    } else {
        echo "libxml_disable_entity_loader 関数は現在の PHP 環境には存在しません。\n";
        echo "リファレンス情報に記載された PHP 8.4.12 では、この関数は削除されています (PHP 8.2.0 以降)。\n";
        echo "PHP 8.0 以降では、外部エンティティの読み込みはデフォルトで無効です。\n";
        echo "XXE対策については、代わりに libxml_set_external_entity_loader() や\n";
        echo "XML読み込み時の LIBXML_NOENT フラグの使用を検討してください。\n";
    }

    echo "\n--- デモンストレーション終了 ---\n";
}

// 関数の実行
demonstrateLibxmlDisableEntityLoader();

libxml_disable_entity_loader()は、XMLの外部エンティティの読み込みを制御するための関数です。これは主に、XXE(XML External Entity)と呼ばれるセキュリティ上の脆弱性を利用した攻撃を防ぐ目的で使用されていました。

ただし、この関数はPHP 8.0.0で非推奨となり、PHP 8.2.0で削除されたため、リファレンス情報にあるPHP 8.4.12のような新しいバージョンでは使用できません。現在のPHPでは、外部エンティティの読み込みはデフォルトで無効になっており、より安全な仕様になっています。

引数にはbool型の値を指定します。true(デフォルト)を渡すと外部エンティティの読み込みが無効になり、falseを渡すと有効になります。戻り値は、この関数を呼び出す前の設定状態をbool値で返します。無効だった場合はtrue、有効だった場合はfalseが返るため、処理後に設定を元に戻す際に利用できます。

サンプルコードは、まずfunction_exists()で関数の存在を確認しています。新しいPHP環境では関数が存在しないため、その旨を伝えるメッセージが表示されます。古い環境では、この関数を使ってエンティティ読み込みを無効にし、処理後に元の状態へ復元する一連の流れを示しています。

この関数はPHP 8.2.0で削除されたため、リファレンス情報のPHP 8.4.12のような新しいバージョンでは使用できません。主な目的はXXE攻撃というセキュリティリスクを防ぐことでしたが、PHP 8.0以降では外部エンティティの読み込みがデフォルトで無効化されており、安全性が向上しています。もし古いPHP環境でこの関数を利用する場合、設定がPHP全体に影響するグローバルなものである点に注意してください。この関数は、実行前の状態を戻り値として返すため、それを利用して処理後に設定を元に戻すのが良い実践です。

【PHP8.x】libxml_disable_entity_loader関数の使い方 | いっしー@Webエンジニア