CVE-2022-41852 Apache Commons JXPath RCE
前言
最近在推特上看到有详情爆出来,就来分析学习一下
环境
引入jxpath依赖即可
|
|
漏洞分析
先来弹个计算器,利用的是ClassPathXmlApplicationContext加载恶意xml触发计算器,这里有个关键点在于ClassPathXmlApplicationContext.new这个.new,既然能够触发xml肯定就是调用了构造函数但是为什么要在这里写个.new呢,直接调试看一下

|
|
先进入到this.compileExpression中看看做了哪些操作

在org.apache.commons.jxpath.ri.JXPathContextReferenceImpl#compileExpression中,compiled是一个hashmap类型且为空,先尝试从compiled取出xpath的value值肯定是为空的,接着进入到parseExpression中

可以看到自行解析compiled中没有的键值对然后赋值给expr,然后返回将键值对赋值给compiled在返回expr

接着进入到this.getValue中,触发构造函数的地方应该就是在这里了,跟进expr.computeValue

在org.apache.commons.jxpath.ri.compiler.ExtensionFunction#computeValue中,先是将expr中的args强制转换赋值给parameters,可以看到在进行function.invoke的时候function为ClassPathXmlApplicationContext的构造函数,而它是在context.getRootContext().getFunction中进行获取的,先跟进看看是怎么转换的

一路跟进到org.apache.commons.jxpath.PackageFunctions#getFunction中,先后进入多次lookupMethod函数,应该为通过name和parameters进行匹配获取对应的函数,跟进去看一下具体是怎么样操作的

先强制类型转换获取parameters的类型,然后进行遍历取出其中的值,接着通过targetClass.getMethod(name, types)获取其函数,但是ClassPathXmlApplicationContext肯定不在String类中所以结果为null,最后在通过for循环遍历targetClass中的函数进行匹配

经过几次lookupMethod后,截取最后一个.前后的值并分别赋值给className和methodName,接着通过Class.forName加载className也就是ClassPathXmlApplicationContext,然后判断methodName的值是否为new,是的话获取其构造函数,否的话获取其静态函数,然后返回值。也就是说该漏洞不仅可以通过构造函数触发,还可以通过public静态函数触发

再来看看function.invoke,并不是常说的反射调用,而是jxpath自己写的的一个invoke调用函数,最后在ConstructorFunction#invoke中触发漏洞


通过javax.naming.InitialContext.doLookup("ldap://127.0.0.1:8899/")来测试一下静态方法调用,nc监听,最后在MethodFunction#invoke中通过反射调用


小结
总结下来就是可以触发任意类的构造函数和public静态函数,可以根据这两个点找gadget,在看的时候经过MoonBack师傅的提醒,该洞还可以链式调用,相应的gadget的范围就更大了
|
|
