ifeilong / feilong

让Java开发更简便的工具库
Apache License 2.0
118 stars 30 forks source link

研究下 XML External Entity Injection XXE #38

Open venusdrogon opened 6 years ago

venusdrogon commented 6 years ago

关于XML解析存在的安全问题指引

https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=23_5

微信支付商户,最近暴露的XML外部实体注入漏洞(XML External Entity Injection,简称 XXE),该安全问题是 由XML组件默认没有禁用外部实体引用导致 ,非微信支付系统存在漏洞。

如果你在使用支付业务回调通知中,存在以下场景有使用XML解析的情况,请务必检查是否对进行了防范。

场景1:支付成功通知; 场景2:退款成功通知; 场景3:委托代扣签约、解约、扣款通知; 场景4:车主解约通知; 场景5:扫码支付模式一回调;

注:APP支付的用户端SDK不受影响,但APP支付成功回调通知里面要检查。

微信支付会通过这几个系统号码通知商户进行安全周知和询问是否授权平台进行安全扫描。 (0755)36560292 (0755)61954612 (0755)1954613 (0755)61954614 (0755)61954615 (0755)61954616 授权检测支付系统操作,不会影响商户系统安全。

检查及修复建议

1.如果您的后台系统使用了官方SDK,请更新SDK到最新版本 SDK的链接:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1 2.如果您是有系统提供商,请联系提供商进行核查和升级修复; 3.如果您是自研系统,请联系技术部门按以下指引核查和修复:

XXE漏洞需要你在代码中进行相应的设置,不同语言设置的内容不同,下面提供了几种主流开发语言的设置指引:

【JAVA】

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException; // catching unsupported features
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
String FEATURE = null;
try {
    // This is the PRIMARY defense. If DTDs (doctypes) are disallowed, almost all XML entity attacks are prevented
    // Xerces 2 only - http://xerces.apache.org/xerces2-j/features.html#disallow-doctype-decl
    FEATURE = "http://apache.org/xml/features/disallow-doctype-decl";
    dbf.setFeature(FEATURE, true);

    // If you can't completely disable DTDs, then at least do the following:
    // Xerces 1 - http://xerces.apache.org/xerces-j/features.html#external-general-entities
    // Xerces 2 - http://xerces.apache.org/xerces2-j/features.html#external-general-entities
    // JDK7+ - http://xml.org/sax/features/external-general-entities 
    FEATURE = "http://xml.org/sax/features/external-general-entities";
    dbf.setFeature(FEATURE, false);

    // Xerces 1 - http://xerces.apache.org/xerces-j/features.html#external-parameter-entities
    // Xerces 2 - http://xerces.apache.org/xerces2-j/features.html#external-parameter-entities
    // JDK7+ - http://xml.org/sax/features/external-parameter-entities 
    FEATURE = "http://xml.org/sax/features/external-parameter-entities";
    dbf.setFeature(FEATURE, false);

    // Disable external DTDs as well
    FEATURE = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
    dbf.setFeature(FEATURE, false);

    // and these as well, per Timothy Morgan's 2014 paper: "XML Schema, DTD, and Entity Attacks"
    dbf.setXIncludeAware(false);
    dbf.setExpandEntityReferences(false);

    // And, per Timothy Morgan: "If for some reason support for inline DOCTYPEs are a requirement, then 
    // ensure the entity settings are disabled (as shown above) and beware that SSRF attacks
    // (http://cwe.mitre.org/data/definitions/918.html) and denial 
    // of service attacks (such as billion laughs or decompression bombs via "jar:") are a risk."

    // remaining parser logic
} catch (ParserConfigurationException e) {
    // This should catch a failed setFeature feature
    logger.info("ParserConfigurationException was thrown. The feature '" +
    FEATURE + "' is probably not supported by your XML processor.");
}
catch (SAXException e) {
    // On Apache, this should be thrown when disallowing DOCTYPE
    logger.warning("A DOCTYPE was passed into the XML document");
}
catch (IOException e) {
    // XXE that points to a file that doesn't exist
    logger.error("IOException occurred, XXE may still possible: " + e.getMessage());
}
DocumentBuilder safebuilder = dbf.newDocumentBuilder();

附录

更多开源库/语言版本的修复建议可参考: https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#C.2FC.2B.2B

venusdrogon commented 6 years ago

https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#C.2FC.2B.2B

Introduction XML eXternal Entity injection (XXE), which is now part of the OWASP Top 10, is a type of attack against an application that parses XML input. This attack occurs when untrusted XML input containing a reference to an external entity is processed by a weakly configured XML parser. This attack may lead to the disclosure of confidential data, denial of service, Server Side Request Forgery (SSRF), port scanning from the perspective of the machine where the parser is located, and other system impacts. The following guide provides concise information to prevent this vulnerability. For more information on XXE, please visit XML External Entity (XXE) Processing.

venusdrogon commented 6 years ago

http://www.freebuf.com/articles/web/126788.html

浅谈XXE攻击

0×00. 介绍 现在越来越多主要的web程序被发现和报告存在XXE(XML External Entity attack)漏洞,比如说facebook、paypal等等。 举个例子,我们扫一眼这些网站最近奖励的漏洞,充分证实了前面的说法。尽管XXE漏洞已经存在了很多年,但是它从来没有获得它应得的关注度。很多XML的解析器默认是含有XXE漏洞的,这意味着开发人员有责任确保这些程序不受此漏洞的影响。

本文主要讨论什么是XML外部实体,这些外部实体是如何被攻击的。

更新:最新微信XXE漏洞案例

0×01. 什么是XML外部实体? 如果你了解XML,你可以把XML理解为一个用来定义数据的东东。因此,两个采用不同技术的系统可以通过XML进行通信和交换数据。 比如,下图就是一个用来描述一个职工的XML文档样本,其中的’name’,'salary’,'address’ 被称为XML的元素。

Image

有些XML文档包含system标识符定义的“实体”,这些XML文档会在DOCTYPE头部标签中呈现。这些定义的’实体’能够访问本地或者远程的内容。比如,下面的XML文档样例就包含了XML ‘实体’。

Image

在上面的代码中, XML外部实体 ‘entityex’ 被赋予的值为:file://etc/passwd。在解析XML文档的过程中,实体’entityex’的值会被替换为URI(file://etc/passwd)内容值(也就是passwd文件的内容)。 关键字’SYSTEM’会告诉XML解析器,’entityex’实体的值将从其后的URI中读取。因此,XML实体被使用的次数越多,越有帮助。

0×02. 什么是XML外部实体攻击? 有了XML实体,关键字’SYSTEM’会令XML解析器从URI中读取内容,并允许它在XML文档中被替换。因此,攻击者可以通过实体将他自定义的值发送给应用程序,然后让应用程序去呈现。 简单来说,攻击者强制XML解析器去访问攻击者指定的资源内容(可能是系统上本地文件亦或是远程系统上的文件)。比如,下面的代码将获取系统上folder/file的内容并呈献给用户。

Image

0×03. 怎么甄别一个XML实体攻击漏洞? 最直接的回答就是: 甄别那些接受XML作为输入内容的端点。 但是有时候,这些端点可能并不是那么明显。在这种情况下,渗透测试人员就必须尝试不同的测试方式,比如修改HTTP的请求方法,修改Content-Type头部字段等等方法,然后看看应用程序的响应,看看程序是否解析了发送的内容,如果解析了,那么则可能有XXE攻击漏洞。

0×04. 如何确认XXE漏洞? 出于演示的目的,我们将用到一个Acunetix维护的demo站点,这个站点就是: http://testhtml5.vulnweb.com/。这个站点可用于测试Acunetix web扫描器的功能。 访问 http://testhtml5.vulnweb.com/ 站点,点击 ‘Login’下面的 ‘Forgot Password’ 链接。注意观察应用程序怎样使用XML传输数据,过程如下图所示:

请求:

Image

响应:

Image

观察上面的请求与响应,我们可以看到,应用程序正在解析XML内容,接受特定的输入,然后将其呈现给用户。为了测试验证XML解析器确实正在解析和执行我们自定义的XML内容,我们发送如下的请求

修改后的请求和响应:

Image

如上图所示,我们在上面的请求中定义了一个名为myentity、值为’testing’的实体。 响应报文清晰地展示了解析器已经解析了我们发送的XML实体,然后并将实体内容呈现出来了。 由此,我们可以确认,这个应用程序存在XXE漏洞。

0×05. 如何进行XXE攻击? Code 1:

1. To read files on same server:

 <?xml version="1.0" encoding="ISO-8859-1"?>

 <!DOCTYPE foo [ 

 <!ENTITY myentity SYSTEM "file:///location/anyfile" >]>

 <abc>&myentity;</abc>

2. To crash the server / Cause denial of service:

 <?xml version="1.0"?>

 <!DOCTYPE lolz [

 <!ENTITY lol "lol">

 <!ENTITY lol2 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">

 <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">

 <!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">

 <!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">

 <!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">

 <!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">

 <!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">

 <!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">

 ]>

 <lolz>&lol9;</lolz>

上面样例代码1中的XXE漏洞攻击就是著名的’billion laughs’(https://en.wikipedia.org/wiki/Billion_laughs)攻击,该攻击通过创建一项递归的 XML 定义,在内存中生成十亿个”Ha!”字符串,从而导致 DDoS 攻击。原理为:构造恶意的XML实体文件耗尽可用内存,因为许多XML解析器在解析XML文档时倾向于将它的整个结构保留在内存中,解析非常慢,造成了拒绝服务器攻击。除了这些,攻击者还可以读取服务器上的敏感数据,还能通过端口扫描,获取后端系统的开放端口。

影响: 此漏洞非常危险, 因为此漏洞会造成服务器上敏感数据的泄露,和潜在的服务器拒绝服务攻击。

补救措施: 上面讨论的主要问题就是XML解析器解析了用户发送的不可信数据。然而,要去校验DTD(document type definition)中SYSTEM标识符定义的数据,并不容易,也不大可能。大部分的XML解析器默认对于XXE攻击是脆弱的。因此,最好的解决办法就是配置XML处理器去使用本地静态的DTD,不允许XML中含有任何自己声明的DTD。

比如下面的Java代码,通过设置相应的属性值为false,XML外部实体攻击就能够被阻止。因此,可将外部实体、参数实体和内联DTD 都被设置为false,从而避免基于XXE漏洞的攻击。

以下是代码的第二段

import javax.xml.parsers.DocumentBuilderFactory;

import javax.xml.parsers.ParserConfigurationException; // catching unsupported features

...

 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

 try {

 // Xerces 1 - http://xerces.apache.org/xerces-j/features.html#external-general-entities

 // Xerces 2 - http://xerces.apache.org/xerces2-j/features.html#external-general-entities

 String FEATURE = "http://xml.org/sax/features/external-general-entities";

 dbf.setFeature(FEATURE, false);

 // Xerces 1 - http://xerces.apache.org/xerces-j/features.html#external-parameter-entities

 // Xerces 2 - http://xerces.apache.org/xerces2-j/features.html#external-parameter-entities

 FEATURE = "http://xml.org/sax/features/external-parameter-entities";

 dbf.setFeature(FEATURE, false);

 // Xerces 2 only - http://xerces.apache.org/xerces2-j/features.html#disallow-doctype-decl

 FEATURE = "http://apache.org/xml/features/disallow-doctype-decl";

 dbf.setFeature(FEATURE, true);

 // remaining parser logic

 ...

 catch (ParserConfigurationException e) {

 // This should catch a failed setFeature feature

 logger.info("ParserConfigurationException was thrown. The feature '" +

 FEATURE +

 "' is probably not supported by your XML processor.");

 ...

 }

 catch (SAXException e) {

 // On Apache, this should be thrown when disallowing DOCTYPE

 logger.warning("A DOCTYPE was passed into the XML document");

 ...

 }

 catch (IOException e) {

 // XXE that points to a file that doesn't exist

 logger.error("IOException occurred, XXE may still possible: " + e.getMessage());.. }
venusdrogon commented 6 years ago

关于dom4j的微信XXE实体注入错误,使用DocumentHelper进行解析的漏洞修补

https://blog.csdn.net/wtbapi/article/details/80944244

SpringMVC中的XXE漏洞测试

https://blog.csdn.net/u011721501/article/details/43940503

https://jira.spring.io/browse/SPR-10806

venusdrogon commented 6 years ago

关于dom4j的微信XXE实体注入错误,使用DocumentHelper进行解析的漏洞修补

7月4日微信发来通知说存在XML实体注入漏洞,请修改。

由于自己的后台采取的dom4j的包,而且当时业务也只是对微信传入的xml进行解析处理,所以就直接使用DocumentHelperparseText的方式进行解析,而没有使用SAXReader的方式进行,在网上搜罗了很多资料,发现处理方式都无法使用。

最后自己在看了dom4j的源代码后,发现DocumentHelper的parseText方法的实现,其实也是SAXReader实现的,再查看SAXReader源码,里面也有一个方式setFeature,于是找到了处理方式

Document doc = null;

SAXReader reader = new SAXReader();

try{
reader.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);
}

catch (SAXException e) {
// On Apache, this should be thrown when disallowing DOCTYPE
wtbapi.Log.log("A DOCTYPE was passed into the XML document","GJ.java文件错误2");
}

String encoding = getEncoding(str);

InputSource source = new InputSource(new StringReader(str));
source.setEncoding(encoding);

doc = reader.read(source);
if (doc.getXMLEncoding() == null) {
  doc.setXMLEncoding(encoding);

}

其中getEncoding(String)方法是DocumentHelper内部的方式

private static String getEncoding(String text)
  {
String result = null;

String xml = text.trim();
if (xml.startsWith("<?xml"))
{
  int end = xml.indexOf("?>");
  String sub = xml.substring(0, end);
  StringTokenizer tokens = new StringTokenizer(sub, " =\"'");
  while (tokens.hasMoreTokens())
  {
String token = tokens.nextToken();
if ("encoding".equals(token))
{
  if (!tokens.hasMoreTokens()) {
break;
  }
  result = tokens.nextToken(); break;
}
  }
}
return result;

  }

有三个包要引入一下

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import java.util.StringTokenizer;
venusdrogon commented 6 years ago

XMLInputFactory (a StAX parser) StAX parsers such as XMLInputFactory allow various properties and features to be set.

To protect a Java XMLInputFactory from XXE, do this:

xmlInputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false); // This disables DTDs entirely for that factory xmlInputFactory.setProperty("javax.xml.stream.isSupportingExternalEntities", false); // disable external entities

venusdrogon commented 6 years ago

Note: The above defenses require Java 7 update 67, Java 8 update 20, or above, because the above countermeasures for DocumentBuilderFactory and SAXParserFactory are broken in earlier Java versions, per: CVE-2014-6517.

venusdrogon commented 4 years ago

XML parsers should not be vulnerable to XXE attacks Vulnerability Blocker Main sources

cwe, owasp-a4 Available Since Apr 02, 2020 SonarAnalyzer (Java) Constant/issue: 15min Allowing access to external entities in XML Parsing could introduce vulnerabilities like SSRF or confidential file disclosures:

Example in XML document:

<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>

&xxe; Jani Reminder Don't forget me this weekend!

Example in XSL document:

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE root [ <!ENTITY content SYSTEM "file:/etc/passwd"> ]>

&content; Example in XSD document: ]> To protect Java XML Parsers from XXE attacks these properties have been implemented: - ACCESS_EXTERNAL_DTD: should be set to "" when processing XML/XSD/XLS files (it looks for external DOCTYPEs) - ACCESS_EXTERNAL_SCHEMA: should be set to "" when processing XML/XSD/XLS files (it looks for external schemalocation ect) - ACCESS_EXTERNAL_STYLESHEET should be set to "" when processing XLS file (it looks for external imports, includes ect); Avoid FEATURE_SECURE_PROCESSING feature to protect from XXE attacks because depending on the implementation: - it has no effect to protect the parser from XXE attacks - or it's just an obscur shortcut (it could set ACCESS_EXTERNAL_DTD and ACCESS_EXTERNAL_SCHEMA to '') Noncompliant Code Examples DocumentBuilderFactory library: String xml = "xxe.xml"; DocumentBuilderFactory df = DocumentBuilderFactory.newInstance(); // Noncompliant DocumentBuilder builder = df.newDocumentBuilder(); Document document = builder.parse(new InputSource(xml)); DOMSource domSource = new DOMSource(document); SAXParserFactory library: String xml = "xxe.xml"; SaxHandler handler = new SaxHandler(); SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser(); // Noncompliant parser.parse(xml, handler); XMLInputFactory library: XMLInputFactory factory = XMLInputFactory.newInstance(); // Noncompliant XMLEventReader eventReader = factory.createXMLEventReader(new FileReader("xxe.xml")); TransformerFactory library: String xslt = "xxe.xsl"; String xml = "xxe.xml"; TransformerFactory transformerFactory = javax.xml.transform.TransformerFactory.newInstance(); // Noncompliant Transformer transformer = transformerFactory.newTransformer(new StreamSource(xslt)); StringWriter writer = new StringWriter(); transformer.transform(new StreamSource(xml), new StreamResult(writer)); String result = writer.toString(); SchemaFactory library: String xsd = "xxe.xsd"; StreamSource xsdStreamSource = new StreamSource(xsd); SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); // Noncompliant Schema schema = schemaFactory.newSchema(xsdStreamSource); Validator library: String xsd = "xxe.xsd"; String xml = "xxe.xml"; StreamSource xsdStreamSource = new StreamSource(xsd); StreamSource xmlStreamSource = new StreamSource(xml); SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); Schema schema = schemaFactory.newSchema(xsdStreamSource); Validator validator = schema.newValidator(); // Noncompliant StringWriter writer = new StringWriter(); validator.validate(xmlStreamSource, new StreamResult(writer)); Compliant Solution DocumentBuilderFactory library: String xml = "xxe.xml"; DocumentBuilderFactory df = DocumentBuilderFactory.newInstance(); df.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); // Compliant df.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); // compliant DocumentBuilder builder = df.newDocumentBuilder(); Document document = builder.parse(new InputSource(xml)); DOMSource domSource = new DOMSource(document); SAXParserFactory library: String xml = "xxe.xml"; SaxHandler handler = new SaxHandler(); SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser(); parser.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); // Compliant parser.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); // compliant parser.parse(xml, handler); XMLInputFactory library: XMLInputFactory factory = XMLInputFactory.newInstance(); factory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); // Compliant factory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); // compliant XMLEventReader eventReader = factory.createXMLEventReader(new FileReader("xxe.xml")); TransformerFactory library: String xslt = "xxe.xsl"; String xml = "xxe.xml"; TransformerFactory transformerFactory = javax.xml.transform.TransformerFactory.newInstance(); transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); // Compliant transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); // Compliant // ACCESS_EXTERNAL_SCHEMA not supported in several TransformerFactory implementations Transformer transformer = transformerFactory.newTransformer(new StreamSource(xslt)); StringWriter writer = new StringWriter(); transformer.transform(new StreamSource(xml), new StreamResult(writer)); String result = writer.toString(); SchemaFactory library: String xsd = "xxe.xsd"; StreamSource xsdStreamSource = new StreamSource(xsd); SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); // Compliant schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); // Compliant Schema schema = schemaFactory.newSchema(xsdStreamSource); Validator library: String xsd = "xxe.xsd"; String xml = "xxe.xml"; StreamSource xsdStreamSource = new StreamSource(xsd); StreamSource xmlStreamSource = new StreamSource(xml); SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); Schema schema = schemaFactory.newSchema(xsdStreamSource); schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); // validators will also inherit of these properties Validator validator = schema.newValidator(); validator.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); // Compliant validator.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); // Compliant StringWriter writer = new StringWriter(); validator.validate(xmlStreamSource, new StreamResult(writer)); See OWASP Top 10 2017 Category A4 - XML External Entities (XXE) OWASP XXE Prevention Cheat Sheet MITRE, CWE-611 - Information Exposure Through XML External Entity Reference MITRE, CWE-827 - Improper Control of Document Type Definition Extend Description