通過JAXB看XML外部實體注入(XML External Entity)
阿新 • • 發佈:2019-01-24
我們先使用JAXB提供的註解標記下java類和XML對映關係:
package jaxb; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Student { @XmlElement(name = "name") private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Student [name=" + name + "]"; } }
下面這個類使用JAXB的API進行物件和xml直接的相互轉換:
xmlToObjectXXE()這個方法解析xml,存在XXE注入;而xmlToObjectSafe是安全的解析方式。package jaxb; import java.io.FileInputStream; import java.io.StringReader; import java.io.StringWriter; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamReader; public class Main { public static void main(String[] args) throws Exception { String xml = readContent("src/jaxb/1.xml"); Object obj = xmlToObjectXXE(xml, Student.class); System.out.println(objectToXML(obj, Student.class)); } public static String readContent(String file) throws Exception { FileInputStream input = new FileInputStream(file); byte[] content = new byte[2 * 1024]; int realBytes = input.read(content); input.close(); return new String(content, 0, realBytes, "UTF-8"); } public static Object xmlToObjectXXE(String xml, Class<?> klass) throws Exception { JAXBContext context = JAXBContext.newInstance(klass); Unmarshaller unmarshaller = context.createUnmarshaller(); return unmarshaller.unmarshal(new StringReader(xml)); } public static Object xmlToObjectSafe(String xml, Class<?> klass) throws Exception { JAXBContext context = JAXBContext.newInstance(klass); XMLInputFactory xif = XMLInputFactory.newFactory(); xif.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false); xif.setProperty(XMLInputFactory.SUPPORT_DTD, true); XMLStreamReader xsr = xif.createXMLStreamReader(new StringReader(xml)); Unmarshaller unmarshaller = context.createUnmarshaller(); return unmarshaller.unmarshal(xsr); } public static String objectToXML(Object obj, Class<?> klass) throws Exception { JAXBContext jaxbContext = JAXBContext.newInstance(klass); Marshaller marshaller = jaxbContext.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8"); marshaller.setProperty(Marshaller.JAXB_FRAGMENT, false); StringWriter writer = new StringWriter(); marshaller.marshal(obj, writer); writer.close(); return writer.toString(); } }
比如我們xml內容是:
<!DOCTYPE student[
<!ENTITY my_outer_entity SYSTEM "file:///c:/demo.txt">
]>
<student>
<name>&my_outer_entity;</name>
</student>
如果使用xmlToObjectXXE得到的結果是:可以明顯地看到XXE攻擊,讀取了c:/demo.txt的內容
如果使用xmlToObjectSafe解析得到結果是: