Java代码审计-XMI注入(XXE)

Java代码审计-XMI注入(XXE)1 XML 注入攻击 1 1 XML 漏洞攻击原理 1 1 1 什么是 XML XML 指可扩展标记语言 EXtensible Markup Language XML 是一种很像 HTML 的标记语言 XML 的设计宗旨是传输数据 而不是显示数据 XML 标签没有被预定义 您需要自行定义标签 XML

大家好,我是讯享网,很高兴认识大家。

1 XML 注入攻击

1.1 XML漏洞攻击原理

1.1.1 什么是XML

XML 指可扩展标记语言(EXtensible Markup Language)。

XML 是一种很像HTML的标记语言。

XML 的设计宗旨是传输数据,而不是显示数据。

XML 标签没有被预定义。您需要自行定义标签。

XML 被设计为具有自我描述性。

XML 是 W3C 的推荐标准。

1.1.2 XML注入漏洞原理

使用不可信数据来构造XML会导致XML注入漏洞也成称为XXE漏洞。一个用户,如果他被允许输入结构化的XML片段,且输入的片段未做任何防御措施,则他可以在XML的数据域中注入XML标签来改写目标XML文档的结构与内容。XML解析器会对注入的标签进行识别和解释。

1.2 XML注入基础知识

1.2.1 DTD

1.2.2 实体ENTITY

XML中的实体类型,一般有下面几种:字符实体、命名实体(或内部实体)、外部普通实体、外部参数实体。除外部参数实体外,其它实体都以字符(&)开始,以字符(;)结束。

  • 字符实体

字符实体类似html中的实体编码,形如:a(十进制)或者a(十六进制)。

  • 命名实体(内部实体)

内部实体又称为命名实体。命名实体可以说成是变量声明,命名实体只能声明在DTD或者XML文件开始部分(<!DOCTYPE>语句中)。

命名实体(或内部实体)语法:

<!ENTITY 实体名称 "实体的值">

如:

<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE root [ <!ENTITY x "xxe1"> <!ENTITY y "xxe2"> ]> <root><x>&x;</x><y>&y;</y></root> 

讯享网

定义实体名称x和y 值为xxe1和xxe2!

&x; 引用实体x;&y引用实体y

  • 外部普通实体

外部实体用于加载外部文件的内容。(显式XXE攻击主要利用外部普通实体)

外部普通实体语法:

讯享网<!ENTITY 实体名称 SYSTEM "URI/URL"> 如: <?xml version="1.0" encoding="utf-8"?> <!DOCTYPe root [ <!ENTITY outfile SYSTEM "outfile.xml"> ]> <root><outfile>&outfile;</outfile></root> 
  • 外部参数实体
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE root [ <!ENTITY % p1"hello"> <!ENTITY % p2 " "> <!ENTITY % p3 "jj"> <!ENTITY dtd SYSTEM "combine.dtd"> %dtd; ]> <root><foo>&content</foo></root> 

combine.dtd中的内容为:

讯享网<!ENTITY content "%param1;%param2;%param3;"> 

上面combine.dtd中定义了一个基本实体,引用了3个参数实体:%p1;,%p2;,%p3;。

解析后…中的内容为hello jj。

1.3 XML注入审计函数

一般在传输数据接口和导入配置等场景可能会用到XML解析,若涉及到XML文件处理的场景要查看是否禁用DTD外部实体,来判断是否存在XXE。常用XML审计函数如下,可搜索如下关键字:

javax.xml.parsers.DocumentBuilderFactory;

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

org.xml.sax.XMLReader

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


1.4 XML注入漏洞危害

读取任意文件

执行系统命令

探查内网端口

攻击内网网站

1.5 XML注入漏洞代码示例

1.5.1 DocumentBuilder ( DOM Read XML )

DocumentBuilder类是JDK自带的类,在该类解析产生的XXE漏洞是有回显的。 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String result=""; try { //DOM Read XML DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(request.getInputStream()); String username = getValueByTagName(doc,"username"); String password = getValueByTagName(doc,"password"); if(username.equals(USERNAME) && password.equals(PASSWORD)){ result = String.format("<result><code>%d</code><msg>%s</msg></result>",1,username); }else{ result = String.format("<result><code>%d</code><msg>%s</msg></result>",0,username); } } catch (ParserConfigurationException e) { e.printStackTrace(); result = String.format("<result><code>%d</code><msg>%s</msg></result>",3,e.getMessage()); } catch (SAXException e) { e.printStackTrace(); result = String.format("<result><code>%d</code><msg>%s</msg></result>",3,e.getMessage()); } response.setContentType("text/xml;charset=UTF-8"); response.getWriter().append(result); } 

1.5.2 saxReader ( DOM4J Read XML )

讯享网saxReader是第三方的库,该类是无回显的 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String result=""; try { //DOM4J Read XML SAXReader saxReader = new SAXReader(); Document document = saxReader.read(request.getInputStream()); String username = getValueByTagName2(document,"username"); String password = getValueByTagName2(document,"password"); if(username.equals(USERNAME) && password.equals(PASSWORD)){ result = String.format("<result><code>%d</code><msg>%s</msg></result>",1,username); }else{ result = String.format("<result><code>%d</code><msg>%s</msg></result>",0,username); } } catch (DocumentException e) { System.out.println(e.getMessage()); } response.setContentType("text/xml;charset=UTF-8"); response.getWriter().append(result); } 

1.5.3 SAXBuilder ( JDOM2 Read XML )

无回显 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String result=""; try { //JDOM2 Read XML SAXBuilder builder = new SAXBuilder(); Document document = builder.build(request.getInputStream()); String username = getValueByTagName3(document,"username"); String password = getValueByTagName3(document,"password"); if(username.equals(USERNAME) && password.equals(PASSWORD)){ result = String.format("<result><code>%d</code><msg>%s</msg></result>",1,username); }else{ result = String.format("<result><code>%d</code><msg>%s</msg></result>",0,username); } } catch (JDOMException e) { System.out.println(e.getMessage()); } response.setContentType("text/xml;charset=UTF-8"); response.getWriter().append(result); } 

1.5.4 SAXParserFactory

讯享网该类也是JDK内置的类,但他不可回显内容,可借助dnslog平台 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //https://blog.csdn.net/u0/article/details/ String result=""; try { //SAX Read XML SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser saxparser = factory.newSAXParser(); SAXHandler handler = new SAXHandler(); saxparser.parse(request.getInputStream(), handler); //为简单,没有提取子元素中的数据,只要调用parse()解析xml就已经触发xxe漏洞了 //没有回显 blind xxe result = String.format("<result><code>%d</code><msg>%s</msg></result>",0,1); } catch (ParserConfigurationException e) { e.printStackTrace(); result = String.format("<result><code>%d</code><msg>%s</msg></result>",3,e.getMessage()); } catch (SAXException e) { e.printStackTrace(); result = String.format("<result><code>%d</code><msg>%s</msg></result>",3,e.getMessage()); } response.setContentType("text/xml;charset=UTF-8"); response.getWriter().append(result); } 

1.5.5 XMLReaderFactory

public String xmlReaderVuln(HttpServletRequest request) { try { String body = WebUtils.getRequestBody(request); logger.info(body); XMLReader xmlReader = XMLReaderFactory.createXMLReader(); xmlReader.parse(new InputSource(new StringReader(body))); // parse xml return "xmlReader xxe vuln code"; } catch (Exception e) { logger.error(e.toString()); return EXCEPT; } 

1.5.6 Digester

讯享网public String DigesterVuln(HttpServletRequest request) { try { String body = WebUtils.getRequestBody(request); logger.info(body); Digester digester = new Digester(); digester.parse(new StringReader(body)); // parse xml } catch (Exception e) { logger.error(e.toString()); return EXCEPT; } return "Digester xxe vuln code"; 

1.5.7 XMLReader

public String XMLReaderVuln(HttpServletRequest request) { try { String body = WebUtils.getRequestBody(request); logger.info(body); SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser saxParser = spf.newSAXParser(); XMLReader xmlReader = saxParser.getXMLReader(); xmlReader.parse(new InputSource(new StringReader(body))); } catch (Exception e) { logger.error(e.toString()); return EXCEPT; } return "XMLReader xxe vuln code"; } 

1.6 XML注入实战案例

这里借用JOYChou老师的Java Sec Code项目做一个演示。

存在漏洞代码示例:

讯享网public String xxeDocumentBuilderReturn(HttpServletRequest request) { try { String xml_con = WebUtils.getRequestBody(request); System.out.println(xml_con); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); StringReader sr = new StringReader(xml_con); InputSource is = new InputSource(sr); Document document = db.parse(is); // parse xml // 遍历xml节点name和value StringBuffer buf = new StringBuffer(); NodeList rootNodeList = document.getChildNodes(); for (int i = 0; i < rootNodeList.getLength(); i++) { Node rootNode = rootNodeList.item(i); NodeList child = rootNode.getChildNodes(); for (int j = 0; j < child.getLength(); j++) { Node node = child.item(j); buf.append(node.getNodeName() + ": " + node.getTextContent() + "\n"); } } sr.close(); System.out.println(buf.toString()); return buf.toString(); } catch (Exception e) { System.out.println(e); return "except"; } } 

要想清楚Java解析XML机制,就要明白以下几行代码意思

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); StringReader sr = new StringReader(xml_con); InputSource is = new InputSource(sr); Document document = db.parse(is); 

1663917156_632d5c64b626f3834ca91.png!small?1663917149799

讯享网<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE joychou [ <!ENTITY xxe SYSTEM "file:///d://1.txt"> ]> <root>&xxe;</root> 

可成功读取xml文件,漏洞利用成功。

1663917199_632d5c8f4ff8cfa687987.png!small?1663917192278

浏览器显示。

1663917206_632d5c967c0a6bf885991.png!small?1663917199477

1.7 XML注入漏洞防御

使用XML解析器时需要设置其属性,禁用DTDs或者禁止使用外部实体。

以上例中DOM - DocumentBuilderFactory为例,防御代码如下:

dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); //禁用DTDs (doctypes),几乎可以防御所有xml实体攻击 //如果不能禁用DTDs,可以使用下两项,必须两项同时存在 dbf.setFeature("http://xml.org/sax/features/external-general-entities", false); //防止外部普通实体POC 攻击 dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false); //防止外部参数实体POC攻击 

防御代码如下:

1663917238_632d5cb69e836fb0bfd07.png!small?1663917231628

Bhnr3v-68)]

1.7 XML注入漏洞防御

使用XML解析器时需要设置其属性,禁用DTDs或者禁止使用外部实体。

以上例中DOM - DocumentBuilderFactory为例,防御代码如下:

讯享网dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); //禁用DTDs (doctypes),几乎可以防御所有xml实体攻击 //如果不能禁用DTDs,可以使用下两项,必须两项同时存在 dbf.setFeature("http://xml.org/sax/features/external-general-entities", false); //防止外部普通实体POC 攻击 dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false); //防止外部参数实体POC攻击 

防御代码如下:

[外链图片转存中…(img-RgQn0mZQ-68)]

最后

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

同时每个成长路线对应的板块都有配套的视频提供:


当然除了有配套的视频,同时也为大家整理了各种文档和书籍资料&工具,并且已经帮大家分好类了。

因篇幅有限,仅展示部分资料,有需要的小伙伴,可以【扫下方二维码】免费领取:

小讯
上一篇 2025-03-29 19:31
下一篇 2025-02-15 13:29

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/60678.html