通过JAXB看XML外部实体注入(XML External Entity)

前端之家收集整理的这篇文章主要介绍了通过JAXB看XML外部实体注入(XML External Entity)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

我们先使用JAXB提供的注解标记下java类和XML映射关系:

  1. package jaxb;
  2.  
  3. import javax.xml.bind.annotation.XmlAccessType;
  4. import javax.xml.bind.annotation.XmlAccessorType;
  5. import javax.xml.bind.annotation.XmlElement;
  6. import javax.xml.bind.annotation.XmlRootElement;
  7.  
  8. @XmlRootElement
  9. @XmlAccessorType(XmlAccessType.FIELD)
  10. public class Student {
  11.  
  12. @XmlElement(name = "name")
  13. private String name;
  14.  
  15. public String getName() {
  16. return name;
  17. }
  18.  
  19. public void setName(String name) {
  20. this.name = name;
  21. }
  22.  
  23. @Override
  24. public String toString() {
  25. return "Student [name=" + name + "]";
  26. }
  27.  
  28. }


下面这个类使用JAXB的API进行对象和xml直接的相互转换:

  1. package jaxb;
  2.  
  3. import java.io.FileInputStream;
  4. import java.io.StringReader;
  5. import java.io.StringWriter;
  6.  
  7. import javax.xml.bind.JAXBContext;
  8. import javax.xml.bind.Marshaller;
  9. import javax.xml.bind.Unmarshaller;
  10. import javax.xml.stream.XMLInputFactory;
  11. import javax.xml.stream.XMLStreamReader;
  12.  
  13. public class Main {
  14.  
  15. public static void main(String[] args) throws Exception {
  16. String xml = readContent("src/jaxb/1.xml");
  17. Object obj = xmlToObjectXXE(xml,Student.class);
  18. System.out.println(objectToXML(obj,Student.class));
  19. }
  20.  
  21. public static String readContent(String file) throws Exception {
  22. FileInputStream input = new FileInputStream(file);
  23. byte[] content = new byte[2 * 1024];
  24. int realBytes = input.read(content);
  25. input.close();
  26. return new String(content,realBytes,"UTF-8");
  27. }
  28.  
  29. public static Object xmlToObjectXXE(String xml,Class<?> klass) throws Exception {
  30. JAXBContext context = JAXBContext.newInstance(klass);
  31. Unmarshaller unmarshaller = context.createUnmarshaller();
  32. return unmarshaller.unmarshal(new StringReader(xml));
  33. }
  34.  
  35. public static Object xmlToObjectSafe(String xml,Class<?> klass) throws Exception {
  36. JAXBContext context = JAXBContext.newInstance(klass);
  37.  
  38. XMLInputFactory xif = XMLInputFactory.newFactory();
  39. xif.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES,false);
  40. xif.setProperty(XMLInputFactory.SUPPORT_DTD,true);
  41. XMLStreamReader xsr = xif.createXMLStreamReader(new StringReader(xml));
  42.  
  43. Unmarshaller unmarshaller = context.createUnmarshaller();
  44. return unmarshaller.unmarshal(xsr);
  45. }
  46.  
  47. public static String objectToXML(Object obj,Class<?> klass) throws Exception {
  48. JAXBContext jaxbContext = JAXBContext.newInstance(klass);
  49. Marshaller marshaller = jaxbContext.createMarshaller();
  50.  
  51. marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,Boolean.TRUE);
  52. marshaller.setProperty(Marshaller.JAXB_ENCODING,"UTF-8");
  53. marshaller.setProperty(Marshaller.JAXB_FRAGMENT,false);
  54.  
  55. StringWriter writer = new StringWriter();
  56. marshaller.marshal(obj,writer);
  57. writer.close();
  58.  
  59. return writer.toString();
  60. }
  61. }
xmlToObjectXXE()这个方法解析xml,存在XXE注入;而xmlToObjectSafe是安全的解析方式。


比如我们xml内容是:

  1. <!DOCTYPE student[
  2.  
  3. <!ENTITY my_outer_entity SYSTEM "file:///c:/demo.txt">
  4. ]>
  5.  
  6. <student>
  7. <name>&my_outer_entity;</name>
  8. </student>


如果使用xmlToObjectXXE得到的结果是:可以明显地看到XXE攻击,读取了c:/demo.txt的内容



如果使用xmlToObjectSafe解析得到结果是:

猜你在找的XML相关文章