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的范围就更大了
|
|