jaxb unmarshal abusable por xml trabalhada ao usar analisador SAX padrão?
Pergunta
Assim, em meu projeto atual eu uso o JAXB RI com o analisador Java padrão do JRE da Sun (que eu acredito é Xerces) para XML arbitrário unmarshal.
Primeiro eu uso XJC para compilar um XSD da seguinte forma:
<?xml version="1.0" encoding="utf-8" ?>
<xs:schema attributeFormDefault="unqualified"
elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="foobar">
...
</xs:element>
</xs:schema>
No "caso bom" tudo funciona conforme projetado. Isso quer dizer que se eu sou XML passado em conformidade com esse esquema, em seguida, JAXB unmarshals-lo corretamente em uma árvore de objetos.
O problema surge quando eu estou passou XML com um DTD referências externas, por exemplo.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foobar SYSTEM "http://blahblahblah/foobar.dtd">
<foobar></foobar>
Ao unmarshalling algo assim, as tentativas parser SAX para carregar a entidade remota ( " http: // somehost / foobar. dtd "), apesar do fato de que esse trecho claramente não está em conformidade com o esquema I compilado anteriormente com XJC.
A fim de contornar este comportamento, desde que eu sei que qualquer XML conformant (de acordo com o XSD Eu compilei) não vai exigir o carregamento de uma entidade remota, eu tenho que definir um EntityResolver personalizado que curto-circuitos do carregamento de todos os remoto entidades. Então, ao invés de fazer algo como:
MyClass foo = (MyClass) myJAXBContext.createUnmarshaller().unmarshal(myReader);
Eu sou forçado a fazer isso:
XMLReader myXMLReader = mySAXParser.getXMLReader();
myXMLReader.setEntityResolver(myCustomEntityResolver);
SAXSource mySAXSource = new SAXSource(myXMLReader, new InputSource(myReader));
MyClass foo = (MyClass) myJAXBContext.createUnmarshaller().unmarshal(mySAXSource);
Então, minha pergunta final é:
Quando unmarshalling com JAXB, deve o carregamento de entidades remotas pelo analisador SAX subjacente ser automaticamente em curto-circuito quando o XML em questão pode ser reconhecido como inválido, sem o carregamento dessas entidades remotas?
Além disso, não esta parece ser uma questão de segurança? Dado que JAX-WS depende de JAXB sob o capô, parece que eu poderia passar XML especialmente criado para qualquer serviço da Web JAX-WS base e causar o anfitrião WS para carregar qualquer URL arbitrário.
Eu sou um novato em relação a isso, então provavelmente há algo que eu estou sentindo falta. Por favor, deixe-me saber se assim!
Solução
Uma pergunta bem trabalhada, que merece uma resposta:)
Algumas coisas a nota:
- O tempo de execução JAXB não é dependente de XML Schema. Ele usa um parser SAX para gerar um fluxo de eventos SAX que ele usa para se ligar para o modelo de objeto. Este modelo de objecto pode ser escrita à mão, ou pode ser gerado a partir de um esquema usando XJC, mas a ligação e o tempo de execução são muito distintos um do outro. Então, você pode saber que as boas conforma entrada XML para o esquema em tempo de execução, mas JAXB não.
- Forçar o tempo de execução para carregar uma referência DTD remoto não constitui uma brecha de segurança. Se há uma verdadeira DTD no final do mesmo, o pior caso é que ele não irá validar. Se não for uma verdadeira DTD, então ele vai ser ignorado.
- DTD é considerado obsoleto, e por isso não há suporte direto para ele no alto nível JAXB API. Se você precisa de um
EntityResolver
, você precisa cavar o API SAX, que você já fez. - Se o seu modelo de classe foi gerada a partir de um esquema XML, então você deve considerar validar contra ela em tempo de execução, usando
SchemaFactory
eUnmarshaller.setSchema()
. Isso irá instruir Xerces para validar os eventos SAX contra o esquema antes de ser passado para JAXB. Isso não vai parar o DTD sendo buscada, mas adiciona uma camada de segurança que você sabe os dados é bom.