CVE-2022-39197 CobaltStrike RCE漏洞学习
前言
学习,据说是由XSS和Swing导致的RCE漏洞。
Java Swing
可以用于构建Java的图形化界面,似乎可以通过捕获beacon,与CobaltStrike服务的交互,最后在CobaltStrike客户端渲染的方式实现RCE。
测试用代码:
1 |
|
可以渲染出一张图片来:
漏洞分析
按照参考文章的说法,script之类的一些标签在Swing里面是无法加载的,所以要在Swing框架下找到新的利用方法,就像JSON/XML反序列化那样的某些危险标签或者标签里面的危险属性。
全局搜索一下HTML类,可以找到javax.swing.text.html.HTML类,可以看到里面存在一个getTag和一个getAttributeKey函数:
1 |
|
下断点后调试可以发现解析html标签和img标签时会经过这个函数,找一下这个tagHashtable表中都有什么标签,可以看到在static静态代码块里面初始化了这个表:
1 |
|
找到Tag.allTags:
1 |
|
可以看到这里有一个可疑的标签OBJECT,继续调试看看Swing怎么处理这个标签,网上追溯可以看到:
1 |
|
保存进一个对象里,然后再通过该对象的getHTMLTag函数返回,跟这个htmlTag相关联的还有一个elem,继续调试看看这个elem是什么:
一个Element对象,但是里面没有什么特别有意思的数据。
寻思着对标签进行分别处理多半要进行标签名的判读,所以全局搜索HTML.Tag.OBJECT,找到渲染时使用的object视图类:
1 |
|
里面只有三个函数,其中getUnloadableRepresentation函数没有用,setParameters函数通过createComponent调用,于是给createComponent函数下一个断点,看看这个函数,前两句是:
1 |
|
看起来可以根据classid属性指定一个类名,修改一下输入HTML继续调试:
1 |
|
然后是:
1 |
|
简单来说就是通过公有的无参构造函数实例化了一个对象,这里写入的Runtime类就因为没有这种构造函数失败了,这里是肯定无法利用的。另外如果输入的类名继承自Component类,则会将object标签中的数据作为该对象的属性,并通过setParameters函数进行反射写入:
1 |
|
以AWTAnimationPanel2类为例,setParameters函数会通过getPropertyDescriptors函数获取其所有属性,至于是getter还是真的属性另说,此时可以注意到属性的值是通过和获取classid同样的方法从标签获取的,且只支持String类型的属性:
1 |
|
修改一下HTML,加上name属性:
1 |
|
发现这样添加的attr不是String,类型不符合导致在获取属性的时候失败:
1 |
|
属性里不行,那应该是从HTML的更下一级标签里面找了,
在ObjectView类的注释里可以看到object标签的使用示例:
1 |
|
很明显name代表属性名,value代表值,试一试:
1 |
|
调试一下,可以看到反射调用setter顺利触发了:
漏洞利用
按照参考文章所说,利用所用的类在CobaltStrike里面,所以先下载好CobaltStrike。
随便从freebuf找了一个CobaltStrike,将cobaltstrike.jar放到项目文件夹里,并配置到项目的libraries中。
根据参考文章,利用函数为JSVGCanvas类的setURI函数:
1 |
|
是一个通过输入的URL加载SVG文件的函数。
按照参考文章,SVG文件可以执行JavaScript代码,仿写一下:
1 |
|
参考文章里的写法会在DOCTYPE部分产生网络问题,这样写就行了。
然后会遇到下一个问题:
看起来是由于依赖中缺失类导致的,虽然跟参考文章的缺失类不一样(大概是因为我用的是只有一个cobaltstrike.jar文件的CobaltStrike环境),根据参考文章,这一步可以通过JavaScript其他用法解决。
关注SVG所用的JavaScript解析函数BaseScriptingEnvironment类的loadScripts函数,可以看到一些有意思的东西:
1 |
|
可以看到,这里根据SVG中的其他数据从一个远程URL加载了一个jar,并根据其中MANIFEST.MF文件的Script-Handler值加载并实例化了一个远程对象,很明显可以通过加载恶意static代码块的方式实现攻击。
看看要求,首先是type为application/java-archive:
1 |
|
然后是URL的来源:
1 |
|
先写一个恶意类:
1 |
|
然后编译成class文件,再写一个MANIFEST.MF:
1 |
|
打包:
1 |
|
然后报错了:
命令行里的居然是Java 11,重新配置一下Java再试试:
1 |
|
改改MANIFEST.MF再来,没弹出来,再改改把package删掉:
1 |
|
尝试一下:
OK了。
题外话
关于类加载器,在加载FXApplet2Adapter这种类的时候:,如
1 |
|
会报错:
1 |
|
原因是FXApplet2Adapter在ext/jfxrt.jar这个文件里面,而其父类Applet2Adapter在deploy.jar里面,能够加载Applet2Adapter的类加载器是用于加载FXApplet2Adapter的类加载器的父类。这就导致了FXApplet2Adapter在发现依赖于Applet2Adapter无法加载到这个类,因为它自身的类路径里没有deploy.jar,也没有父类可以委派。