这篇文章主要介绍“Java 7u21链原理是什么”,在日常操作中,相信很多人在Java 7u21链原理是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java 7u21链原理是什么”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!jdk7u21 链,是一个不需要借助第三方库就能实现的链。影响版本
我们先来看看ysonerial里的payload是怎么写的,然后沿着其思路进行分析我们看到,ysonerial的payload上来就通过Gadgets.createTemplatesImpl(command) 试图创建一个TemplatesImpl类。 createTemplatesImpl源码如下,我们发现创建TemplatesImpl类后又通过反射和javassist做了许多操作。那么为什么要创建这个类并且调用反射和javassist机制呢?先不急,我们看一下TemplatesImpl源码。首先TemplatesImpl类中有个方法defineTransletClasses,它的主要代码如下也就是说通过这个方法可以将_bytecodes数组中的字节还原成一个类,存储到_class变量中。接下来如果我们能找到调用defineTransletClasses方法并执行了_class[].newinstance() 这样的的代码的方法,就能实例化从字节得到的类了,从而就能执行类中的静态代码块和构造函数了! 所以接下来我们需要去寻找这种方法。 通过搜索defineTransletClasses,我们找到了有如下三个方法调用了defineTransletClasses方法:其中,getTransletInstance方法是唯一符合“调用了defineTransletClasses且有_class[].newinstance()”的方法,其代码如下那么,getTransletInstance是一个private方法,我们不能直接调用它,在那里能去调用它呢?答案是newTransformer方法OK.我们找到了触发7u21链的一个核心点了。我们写个小demo来通过TemplatesImpl实现代码执行 小demo的实现思路为:通过javassist动态生成一个恶意类(构造方法或者静态代码块有恶意代码),然后通过反射生成一个TemplatesImpl对象并设置各个变量的值,然后调用一下TemplatesImpl对象的newTransformer方法即可造成代码执行,代码如下但仅仅是这样,肯定是不够的。我们继续看ysoserial源码可以看到动用了AnnotationInvocationHandler这个东西.这个类原本的作用是作为Annotation 类的动态代理我们把目光聚焦于invoke方法——动态代理的核心它会检测传入的方法中是否有符合 名为equals,只有一个Object类型参数。若是,则调用equalsImpl方法并传入方法中的参数。 跟进equalsimpl方法发现会invoke 传入参数中的所有方法。 那么接下来我们就可以按照下面的思路写一个命令执行小demo:创建一个包含恶意代码的TemplatesImpl实例,通过AnnotationInvocationHandler创建任意一个代理对象,然后代理对象调用equals方法传入参数为恶意TemplatesImpl对象,即可造成恶意代码执行 看到这里一定一头雾水,看看demo也许会好一点我们慢慢看看逻辑,在proxy.equals处下断点,调试 毫无疑问会进入到此处:AnnotationInvocationHandler的invoke方法。然后参数符合if判断,调用equalsImpl方法,并传入参数为恶意TemplatesImpl对象,接下来就是进入反射调用处遍历var2变量中的方法,并由我们的恶意对象来执行。————此处插一下var2变量的来历注意此处的getMemberMethods方法,它实质上是通过反射获得this.type中的所有方法。而this.type是在该对象构造方法中传入的第一个参数。getMemberMethods:构造方法:————回到正题由于我们通过反射传入构造方法的第一个参数是Templates.class,所以它会遍历Templates类中的所有方法。这个类其实是TemplatesImpl的接口类,它的代码如下所以var2中存储的方法只有两个,newTransformer和getOutputProperties。 然后当遍历到newTransformer方法时,就会通过反射调用达到 eviltemplatesImpl.newTransformer() 的效果,从而导致恶意TemplatesImpl对象中的恶意代码被执行。这里承接上面说的,为什么初始化AnnotationInvocationHandler对象时传免费云主机域名入的第一个参数(即this.type)是Templates.class,而不是TemplatesImpl.class 诚然,这两个类对象都有方法newTransformer。但是如果传入TemplatesImpl.class,在遍历其中方法并通过反射执行时会出现错误:equalsImpl中的反射调用是不传入参数的而TemplatesImpl中有许多需要传入参数才能被正常使用的方法,如果不传入参数就反射调用就会抛出异常,以至于在遍历到newTransformer方法前就会抛出异常,从而导致代码执行不被实现。仅仅是这样,也还是不够的,我们还是得手动调用equals才能导致代码执行,反序列化点在哪里?ysoserial的payload中出现了此类。LinkedHashSet继承自HashSet类,它的readObject方法也是从HashSet继承而来的。我们看看readObject方法的构造它的主要亮点在for循环里面:遍历传入的序列化对象,将其反序列化后,再传入put方法所以我们再来跟进一下map.put方法注意我们添加注释那一行,有一个var1.equals(var6))) 其中var1和var6我们都是可以控制的:var1即传入的反序列化对象(恶意TemplatesImpl),var6实际上也是我们传入的反序列化对象(恶意AnnotationInvocationHandler代理对象)。但是想要执行var1.equals(var6))) 则必须要让 var5.hash == var3 为true 且 (var6 = var5.key) == var1为false. 怎么做到呢?注意put方法的第5行,对传入的反序列化对象调用了hash方法。我们跟进hash方法发现会执行传入的参数对象的hashCode()方法 当我们传入的参数为恶意AnnotationInvocationHandler代理对象时,会调用代理对象中的invoke方法。对于AnnotationInvocationHandler而言当判断到执行hashCode方法时,实质上会执行AnnotationInvocationHandler中的hashCodeImpl方法我们跟进hashCodeImpl这个方法会遍历this.memberValues属性(这个属性实质上就是HashMap内添加的属性),然后对其中每一项键值属性进行进行位运算并累加其中memberValueHashCode函数我们也可以跟进一下发现只要传入参数不为数组,就调用它的hashCode函数并返回。我们来梳理一下,怎么才能调用到put方法里的equals触发代码执行: payload阶段:建立一个map变量,其key为特殊的一个值:f5a5a608,这个值的hashCode是0,然后值为恶意templatesImpl类,然后以这个map变量为参数建立AnnotationInvocationHandler代理对象。再向HashMap里放入一个值,键为恶意TemplatesImpl对象, 再放入一个值,键为恶意AnnotationInvocationHandler对象。 (LinkedHashSet会让HashMap有序,从而在反序列化的时候能按顺序依次从HashMap读取对象。如果用HashSet,则会在反序列化时报错)反序列化阶段:随后在readObject时,TemplatesImpl先被put方法调用。然后在put方法里通过hash()方法获得其hash,并将其录入到它的hash属性里,然后写入到HashMap的存储队列里。然后AnnotationInvocationHandler再被put方法调用在对其使用hash方法获得hash时,会因其是一个代理类的缘故在hash函数内部调用hashCode()方法时会调用其代理方法hashCodeImpl。随后在hashCodeImpl内部遍历this.memberValues变量(也就是之前初始化时放入的map变量)将每一项的key值的hashCode与传入map vaule值作为参数的memberValueHashCode方法进行异或。 这个memberValueHashCode方法会判断传入的值是否为数组,若不是数组则直接返回参数的hashCode()。因为我们之前初始化代理对象时传入的是一个键为f5a5a608,值为eviltemplates的map,所以以上hash计算最终得到的结果,便是0^(templatesImpl.hashCode()). 也就是templatesImpl.hashCode()。所以也就是说AnnotationInvocationHandler对象作为参数传入被hash方法执行后的结果,就相当于是hash(eviltemplates)随后这个值来到if判断逻辑,它遍历之前的值,并将遍历得到的值赋给var5上一个值的hash(也就是eviltemplates的hash)与AnnotationInvocationHandler对象的hash(也还是eviltemplates的hash)相同,但是AnnotationInvocationHandler对象与eviltemplates对象并不相同,所以便触动了equals,代码执行成功。纵观以上三个类,我们可以写出payload看一下调用栈更直观的调用链到此,关于“Java 7u21链原理是什么”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注云编程开发博客网站,小编会继续努力为大家带来更多实用的文章!
这篇文章主要讲解了“linux如何替换文件内容”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“linux如何替换文件内容”吧! 在linux中,可以利用sed命令替换文件内容,该命令用于利用脚本来处理文本文件,当…
免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。