Fechando o XXE
A defesa completa recusa o DTD; sem DTD não há onde declarar entidade, e todas as variantes somem.
Todas as variantes do XXE (ler arquivo, SSRF, vazamento fora de banda, billion laughs) dependem de uma coisa: o parser aceitar o DTD e processar o que ele declara. Então a defesa mais forte é a mais simples: recusar o DTD por inteiro. Sem <!DOCTYPE>, não há onde declarar entidade, e as quatro variantes fecham de uma vez.
Desligar só a expansão de entidades gerais não basta: o DTD continua sendo processado, as entidades de parâmetro ainda rodam (vazamento fora de banda) e o billion laughs ainda cresce. Por isso o botão que importa é o do DTD.
O ajuste tem o mesmo espírito em cada biblioteca:
- Java:
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true). - Python: use o pacote
defusedxmlno lugar da biblioteca padrão. - libxml2 (e lxml): não ligue as opções
NOENTnemDTDLOAD. - .NET:
DtdProcessing = DtdProcessing.Prohibit.
Em todas, a ideia é a mesma: não aceitar DTD. Se o seu formato realmente precisa de um, pelo menos nunca resolva entidades externas e limite a expansão.