如何使用修复 XXE 漏洞时出现的 JAXB 修复此 Unmarshal 异常?
How to fix this Unmarshal Exception with JAXB that arose on fixing XXE vulnerabilites?
我们要处理的XML消息的格式是这样的:
<?xml version="1.0" encoding="UTF-8"?>
<ns0:MessageType xmlns:ns0="http://www.path.to/some/schema.xsd">
<ns0:NonRelevantBody>
....
</ns0:NonRelevantBody>
</ns0:MessageType>
收到异常:
javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"ns0:MessageType"). Expected elements are <{http://www.path.to/some/schema.xsd}MessageType>
上述异常发生在com.xmlprocessor.MessageParserclass。
上述 class 中的代码曾经如此(并且已经工作了很长时间):
StringReader stringReader = new StringReader(xmlMessageAsString);
JAXBContext context = new JAXBContext.newInstance(MessageObjectFactory.class);
Unmarshaller unmarshalr = context.createUnmarshaller();
this.messageTypeContent = (MessageTypeContent) unmarshalr.unmarshal(stringReader);
事实证明,这会给你带来糟糕的 XXE 案例。因此,我们尝试了一些非常相似的东西 DocumentBuilder、SAXParser 等来禁用外部实体、Doctype 声明等。所有人都给了我们上面提到的完全相同的例外。无论如何,这里是 SAXParser 的变化:
StringReader stringReader = new StringReader(xmlMessageAsString);
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setFeature("http://xml.org/sax/features/external-general-entities", false);
spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
Source xmlSource = new SAXSource(spf.newSAXParser().getXMLReader(), new InputSource(stringReader));
JAXBContext context = new JAXBContext.newInstance(MessageObjectFactory.class);
Unmarshaller unmarshalr = context.createUnmarshaller();
this.messageTypeContent = (MessageTypeContent) unmarshalr.unmarshal(xmlSource);
com.xmlprocessor.MessageTypeContentclass的代码不变:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"messageType",
"messageApprovalType"
})
@XmlRootElement(name = "MessageType")
public class MessageTypeContent {
// Likely irrelevant unless you say so.
}
我尝试了很多方法,包括将 namespace="ns0" 或 namespace="http://www.path.to/some/schema.xsd" 添加到@XmlRootElement 注释,它会在运行时导致相同异常的相似版本。
请注意代码中没有语法错误。我的任何想法都在把它变成一个问题的过程中。我完全有可能 git 错过了一些非常基本的东西。如果您能指出来,我将不胜感激。谢谢。
让 sax 解析器命名空间感知解决了这个问题:
spf.setNamespaceAware(true);
到头来,无事生非
我们要处理的XML消息的格式是这样的:
<?xml version="1.0" encoding="UTF-8"?>
<ns0:MessageType xmlns:ns0="http://www.path.to/some/schema.xsd">
<ns0:NonRelevantBody>
....
</ns0:NonRelevantBody>
</ns0:MessageType>
收到异常:
javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"ns0:MessageType"). Expected elements are <{http://www.path.to/some/schema.xsd}MessageType>
上述异常发生在com.xmlprocessor.MessageParserclass。 上述 class 中的代码曾经如此(并且已经工作了很长时间):
StringReader stringReader = new StringReader(xmlMessageAsString);
JAXBContext context = new JAXBContext.newInstance(MessageObjectFactory.class);
Unmarshaller unmarshalr = context.createUnmarshaller();
this.messageTypeContent = (MessageTypeContent) unmarshalr.unmarshal(stringReader);
事实证明,这会给你带来糟糕的 XXE 案例。因此,我们尝试了一些非常相似的东西 DocumentBuilder、SAXParser 等来禁用外部实体、Doctype 声明等。所有人都给了我们上面提到的完全相同的例外。无论如何,这里是 SAXParser 的变化:
StringReader stringReader = new StringReader(xmlMessageAsString);
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setFeature("http://xml.org/sax/features/external-general-entities", false);
spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
Source xmlSource = new SAXSource(spf.newSAXParser().getXMLReader(), new InputSource(stringReader));
JAXBContext context = new JAXBContext.newInstance(MessageObjectFactory.class);
Unmarshaller unmarshalr = context.createUnmarshaller();
this.messageTypeContent = (MessageTypeContent) unmarshalr.unmarshal(xmlSource);
com.xmlprocessor.MessageTypeContentclass的代码不变:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"messageType",
"messageApprovalType"
})
@XmlRootElement(name = "MessageType")
public class MessageTypeContent {
// Likely irrelevant unless you say so.
}
我尝试了很多方法,包括将 namespace="ns0" 或 namespace="http://www.path.to/some/schema.xsd" 添加到@XmlRootElement 注释,它会在运行时导致相同异常的相似版本。
请注意代码中没有语法错误。我的任何想法都在把它变成一个问题的过程中。我完全有可能 git 错过了一些非常基本的东西。如果您能指出来,我将不胜感激。谢谢。
让 sax 解析器命名空间感知解决了这个问题:
spf.setNamespaceAware(true);
到头来,无事生非