W3docs

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): bool

Parâmetros

ParâmetroTipoDescrição
$disablebooltrue 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_NONET oferece 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_NONET quando também quiser bloquear o acesso à rede.
  • Migrando código antigo? Substitua libxml_disable_entity_loader(true) pelo sinalizador LIBXML_NONET em cada carregamento, ou encapsule a chamada em function_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.

Prática

Prática
Qual é a função do método libxml_disable_entity_loader() no PHP?
Qual é a função do método libxml_disable_entity_loader() no PHP?
Was this page helpful?