OWASP Top 10中的另一个注入漏洞是XML外部实体注入(XXE),它是在解析XML输入时产生的一种漏洞,漏洞原理和黑盒挖掘技巧见之前的文章:XML外部实体(XXE)注入原理解析及实战案例全汇总,这里从代码层角度挖掘XXE漏洞。
XML解析相关的漏洞除了XXE,还有XML注入和XEE(实体膨胀)等。
还是以Webgoat的一个案例讲解,审计的思路依旧是:针对特定功能进行抓包,定位到相关代码,追踪利用链,判断是否存在问题,漏洞验证/利用。
通过抓包得到请求路径,POST 请求的正文是一个标准格式的XML:
Spring Boot微服务框架处理各种请求时,是通过里面的注解,所以通过注解xxe/simple找到对应类SimpleXXE.java:
@Autowiredprivate Comments comments;@PostMapping(path = "xxe/simple", consumes = ALL_VALUE,produces = APPLICATION_JSON_VALUE)@ResponseBody public AttackResult createNewComment(@RequestBody String commentStr)throws Exception { String error = ""; try { Comment comment = comments.parseXml(commentStr); comments.addComment(comment, false); if (checkSolution(comment)) { return trackProgress(success().build()); } } catch (Exception e) { error = ExceptionUtils.getFullStackTrace(e);
做代码审计工作,大部分时间都是找到关键代码,一行一行代码去嚼,每一句是什么意思、做了什么事情,读得多了,速度自然就快。
比如上面这段代码,首先@表示注解:
@PostMapping注解是url的Map映射,consumes和 produces则是post请求的两个参数,@ResponseBody表示将方法的返回结果直接写入 HTTP返回包的正文body中。@RequestBody String commentStr,表示将请求中的数据写入到commentStr的String对象中。
然后看代码层面:
第一句,必须看懂private Comments comments;是对象的典型定义办法,comments对象是抽象类Comments的一个实例,原则上引用了哪个类我们就要跟踪过去,后续定义了createNewComment方法,顾名思义是创建新的评论,看方法里实现了什么操作,异常try中实例化了另一个Comment类,调用的是comments的parseXml方法,最后addComment进行新增评论。
跟进两个类,Comment.java定义了几个变量,不用关注:
public class Comment { private String user; private String dateTime; private String text;}
跟进Comments.java,里面有三个方法,其中调用的parseXml方法描述了如何处理commentStr:
protected Comment parseXml(String xml)throws Exception { JAXBContext jc = JAXBContext.newInstance(Comment.class); XMLInputFactory xif = XMLInputFactory.newFactory(); xif.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, true); xif.setProperty(XMLInputFactory.IS_VALIDATING, false); xif.setProperty(XMLInputFactory.SUPPORT_DTD, true); XMLStreamReader xsr = xif.createXMLStreamReader(new StringReader(xml)); Unmarshaller unmarshaller = jc.createUnmarshaller(); return (Comment) unmarshaller.unmarshal(xsr);}
审计XXE漏洞时对这段代码要保持敏感,这是xml解析的的典型接口Unmarshaller,也是发现XXE的搜索特征之一。
这里parseXml方法做的主要操作是:获取一个JAXBContext的实例名为jc——>js创建一个Unmarshaller对象——>执行unmarshaller方法将xml格式字符串xsr反序列化为java对象得到comment。反序列过程中解析了XML,也是这个过程导致了XXE注入。
最后在xxe/simple数据包处构造参数为payload,经过调用链解析xml数据进行特定攻击。
三、挖掘技巧
挖掘XXE漏洞的关键是找到代码是否涉及xml解析——>xml输入是否是外部可控——>是否禁用外部实体(DTD),若三个条件满足则存在漏洞。
功能层面XML解析一般在导入配置、数据传输接口等需对xml数据进行处理的场景,代码层面需要关注xml解析的几种实现接口,定位到关键代码后看是否有禁用外部实体的相关代码,从而判断是否存在XXE。
解析XML常见的方法有四种,即:DOM、DOM4J、JDOM 和SAX,部分XML解析接口如下:
javax.xml.parsers.DocumentBuilderjavax.xml.stream.XMLStreamReaderorg.jdom.input.SAXBuilderorg.jdom2.input.SAXBuilderjavax.xml.parsers.SAXParserorg.dom4j.io.SAXReaderorg.xml.sax.XMLReaderjavax.xml.transform.sax.SAXSourcejavax.xml.transform.TransformerFactoryjavax.xml.transform.sax.SAXTransformerFactoryjavax.xml.validation.SchemaFactoryjavax.xml.bind.Unmarshallerjavax.xml.xpath.XPathExpressionorg.apache.commons.digester3.Digester
在定位XXE漏洞的时候可以使用的搜索关键词有:
Documentbuilder|DocumentBuilderFactory|SAXReader|SAXParser|SAXParserFactory|SAXBuilder|TransformerFactory|reqXml|getInputStream|XMLReaderFactory|.newInstance|SchemaFactory|SAXTransformerFactory|javax.xml.bind|XMLReader|XmlUtils.get|Validator
使用XML库的Java应用程序易受到XXE的攻击,因为大多数JavaXML解析器的默认设置是启用DTD。所以使用XML解析器时需要设置其属性,禁止使用外部实体,以上例中SAXReader为例,安全的使用方式如下:
sax.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);sax.setFeature("http://xml.org/sax/features/external-general-entities",false);sax.setFeature("http://xml.org/sax/features/external-parameter-entities",false);
其它XML解析器的安全使用可参考:
https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html
需要指出的是,若只禁用DTD未禁用Doctype,无法进行SSRF等攻击但仍可进行DOS攻击(Billion laughs attack):
<?xml version="1.0"?><!DOCTYPE lolz [ <!ENTITY lol"lol"> <!ELEMENT lolz(#PCDATA)> <!ENTITY lol1"&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;"> <!ENTITY lol2"&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;"> <!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>
对一个CMS的webservice接口类YesbWebServiceImpl进行审计:
主要操作是定义了一个auth方法,形参是xmlSource,最终返回的是yesbOuterService类的auth方法,跟进:
继续跟进busiInvoke方法:
进行xmlToBean操作,跟进:
调用了getDocumentFromString方法,跟进:
发现这个方法内使用SAXReader对xml数据进行解析,且这段代码未禁用DTD,故存在XXE漏洞,其他场景的XXE漏洞挖掘过程也类似。