libxml_disable_entity_loader()
Aprenda sobre a função libxml_disable_entity_loader() no PHP, para que servia, por que foi removida e como escrever código XML seguro hoje.
A função libxml_disable_entity_loader() do PHP era utilizada para ativar ou desativar o carregamento de entidades externas em todos os documentos XML analisados pela extensão libxml. Esta página explica o que a função fazia, o ataque XML External Entity (XXE) contra o qual ela protegia, por que foi removida e como escrever código de análise XML seguro no PHP moderno.
Importante: libxml_disable_entity_loader() foi descontinuada no PHP 8.0 e removida no PHP 8.1. Se você está no PHP 8.1 ou mais recente, chamá-la gera um erro fatal. Use as alternativas seguras abaixo.
O que libxml_disable_entity_loader() Fazia
libxml_disable_entity_loader() era um utilitário PHP embutido que alternava um sinalizador global dentro da libxml — a biblioteca C que alimenta o DOMDocument e o SimpleXML do PHP. Quando o sinalizador estava ativo, a libxml se recusava a resolver entidades externas: referências dentro de um documento XML que apontam para um recurso externo, como um arquivo local (file:///etc/passwd) ou uma URL remota.
Bloquear essa resolução era a forma padrão de se defender contra ataques XML External Entity (XXE). Em um ataque XXE, o invasor envia um payload XML cujo DOCTYPE declara uma entidade que aponta para um recurso sensível:
<?xml version="1.0"?>
<!DOCTYPE data [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<data>&xxe;</data>Se o parser resolver &xxe;, o conteúdo de /etc/passwd acaba no documento analisado — que a aplicação pode então exibir, registrar ou armazenar. O mesmo truque permite server-side request forgery (SSRF, apontando a entidade para uma URL interna) e negação de serviço (a bomba de expansão de entidades "billion laughs").
Sintaxe
libxml_disable_entity_loader(bool $disable = true): boolParâmetros
| Parâmetro | Tipo | Descrição |
|---|---|---|
$disable | bool | true desativa o carregamento de entidades externas; false reativa. O padrão é true. |
Valor de retorno
Retorna o valor anterior do sinalizador como boolean, de modo que era possível restaurar o estado anterior após uma única análise.
Uso Legado
No PHP 7.x e anteriores, proteger uma análise ficava assim. A chamada é encapsulada em function_exists() para que o mesmo código continue funcionando no PHP 8.1+, onde a função não existe mais:
<?php
// Disable external entities (deprecated in PHP 8.0, removed in 8.1).
if (function_exists('libxml_disable_entity_loader')) {
libxml_disable_entity_loader(true);
}
// Load an XML file into a DOMDocument object.
$doc = new DOMDocument();
if (!$doc->load('example.xml')) {
die('Failed to load XML file.');
}
?>Um padrão mais seguro e comum era capturar o valor anterior e restaurá-lo, para que a desativação de entidades não vazasse para análises não relacionadas em outra parte da requisição:
<?php
$previous = libxml_disable_entity_loader(true);
$doc = new DOMDocument();
$doc->loadXML($untrustedXml);
// Restore the global flag for the rest of the request.
libxml_disable_entity_loader($previous);
?>Alternativas Seguras no PHP Moderno
Duas mudanças no PHP moderno tornaram a função desnecessária:
- libxml 2.9+ desativa o carregamento de entidades externas por padrão. Desde essa versão (distribuída com o PHP há anos), entidades externas de DTD não são resolvidas, a menos que você as solicite explicitamente. É por isso que a função se tornou redundante e foi removida.
LIBXML_NONEToferece controle por chamada. Em vez de alternar um sinalizador global, você passa um sinalizador para a chamada de carregamento específica, que bloqueia o acesso à rede durante a análise:
<?php
$doc = new DOMDocument();
// Parse without ever touching the network — no SSRF, no remote entities.
$doc->load('example.xml', LIBXML_NONET);
?>Se você precisar suportar DTDs mas ainda quiser reforço de segurança, evite LIBXML_DTDLOAD / LIBXML_NOENT em entradas não confiáveis, pois esses sinalizadores reativam exatamente o comportamento do qual o XXE depende. O padrão mais seguro é simplesmente não passá-los:
<?php
$doc = new DOMDocument();
// Default flags (0): no entity substitution, no DTD loading from untrusted XML.
$doc->loadXML($untrustedXml);
// SimpleXML follows the same secure default.
$xml = simplexml_load_string($untrustedXml);
?>Para inspecionar problemas de análise em vez de emitir avisos brutos, combine o carregamento com libxml_use_internal_errors() e leia-os via libxml_get_errors().
Quando Usar Isso?
Você só encontrará libxml_disable_entity_loader() ao ler ou manter código PHP 7 legado. Para qualquer código que você escreva hoje:
- No PHP 8.1+, não faça nada especial para entidades — o padrão seguro já se aplica. Adicione
LIBXML_NONETquando também quiser bloquear o acesso à rede. - Migrando código antigo? Substitua
libxml_disable_entity_loader(true)pelo sinalizadorLIBXML_NONETem cada carregamento, ou encapsule a chamada emfunction_exists()para que ela não faça nada em runtimes novos.
Conclusão
libxml_disable_entity_loader() foi por muito tempo a principal defesa contra ataques XXE, mas dependia de um sinalizador global frágil e foi removida desde o PHP 8.1. O PHP moderno é seguro por padrão graças à libxml 2.9+, e LIBXML_NONET oferece controle explícito por análise. Para mais informações sobre a pilha XML do PHP, veja a visão geral da extensão libxml e trabalhando com o XML DOM.