欢迎访问Sunbet官网(www.sunbet.us),Allbet欧博官网(www.ALLbetgame.us)!

首页Sunbet_安全防护正文

从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果

b9e08c31ae1faa592020-08-12231安全技术漏洞分析

前言

作为一名安全研究人员(java安全菜鸡),知道拿到exp怎么打还不够,还得进一步分析exp构造原理与漏洞原理才行。本篇文章主要分析FastJson1.2.24中针对TemplatesImpl链的构造原理以及ysoserial中针对jdk7u21基于TemplatesImpl加动态代理链的构造原理。内容可能巨详细,希望没接触过这部分的同学可以耐心看下去。

1.TemplatesImpl初相识

FastJson1.2.24中基于com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl这条链的入口点在TemplatesImpl的getOutputperties函数。当然本篇文章不再描述具体如何到这一步,有兴趣的可以参考我之前的一篇文章。一步一步学习某Json1.2.47远程命令执行漏洞 因此在下图所示下断点在此,这里环境为jdk7u21。 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第1张 这里首先将调用newTransformer(),首先定义类TransformerImpl的对象,其入口参数第一个为Translet的对象 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第2张 因为此时调用了getTransletInstance(),跟进看看 其返回的是一个Translet类的对象,这里面判断_name 不能为null,否则就拿不到Tranlet对象,后面_class能不能为null,先留着,但是这里明显看到后面要用到_class 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第3张 这里要用到_class,说明_class里面肯定是有东西的,要么是我们自己赋值,要么就是通过上面的defineTransletClasses()得到了,我们先跟进defineTransletClasses()看看 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第4张 这里首先判断_bytecodes不能为null,为null将抛出错误信息 接着这里将拿到类加载器,通过它我们就可以对目标类进行加载,我们知道classloader除了调用loadclass来加载类以外,还可以调用findclass里的definedclass来通过加载字节码来在jvm中加载类,那么它肯定是classloader的子类,跟进看看其确实继承自ClassLoader,并且也看到了熟悉的defineclass函数,我们只要知道此时经过该类的definclass就能进行类的加载 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第5张 继续往下看,下图中实际上取的是_bytecodes[i],并且i的范围也是我们可控的,这里我们知道defineClass是可以通过字节数组来在JVM创建类的,所以这里通过将恶意类的字节码放到_bytecodes里面就能够加载到JVM里 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第6张 接着将拿到刚刚加载到JVM中的类的父类要求其父类必须是ABSTRACT_TRANSLET,不满足则放到_auxlclass里面,要是新加载的所有类的父类没有一个是ABSTRACT_TRANSLET的话,后面此时_transletIndex < 0处的判断就要报错,因为_transletIndex初始值为-1 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第7张 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第8张 此时我们已经知道通过defineTransletClasses函数我们可以通过defineclass来从_bytecodes中加载恶意类,所以我们肯定要让这里的_class为null 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第9张 我们已经知道_class数组中存储的是加载进来的恶意类,下标_transletIndex就是该恶意类对应的下标,所以接着就调用newInstance()来实例化我们的恶意类,那么我们把要执行的命令放在恶意类的static区或者构造方法中都可以 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第10张 其中我们的其中恶意类如下,至于要声明两个transform是由于这里是继承自抽象类,所以在其子类中必须实现,这里不声明的话idea也会提示让你实现,idea真香2333~ 事实也证明如此,我们可以clac了 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第11张 并且经过以上分析最终的payload可以缩减为以下形式: 整个调用过程挺短的,实际上就是 TemplatesImpl -> getOutputProperties() TemplatesImpl -> newTransformer() TemplatesImpl -> getTransletInstance() 此时在getTransletInstance()函数中将调用恶意类的构造函数,即 _class[_transletIndex].newInstance()导致RCE

2.AnnotationInvocationHandler完美链接

这一部分的分析主要就是通过最外层的readObject反序列化直达getOutputProperties()的调用,即newTransformer()的调用。而ysoserial中已经包含了该链的构造过程,其getobject函数就能拿到该链最外层的对象,而调试ysoserial也很容易,不传命令的话会默认传calc.exe 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第12张 这里我们传入要执行的命令后调用createTemplatesImpl即可,那么我们可以看看yso中是如何构造该对象的 这里首先通过class.forname获得了三个我们构造该链要用到的类,然后将要执行的命令和这三个类传入createTemplatesImpl 来返回一个经过精心构造的TemplatesImpl对象 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第13张 这里首先newInstance()获得一个初始的TemplatesImpl对象,用于后面的装饰,然后创建首先创建一个CtClass的容器,我们可以用它按需读取类文件来构造 CtClass 对象,并且保存 CtClass 对象以便以后使用 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第14张 Java 字节码以二进制的形式存储在 .class 文件中,每一个 .class 文件包含一个 Java 类或接口。Javaassist 就是一个用来 处理 Java 字节码的类库。它可以在一个已经编译好的类中添加新的方法,或者是修改已有的方法,并且不需要对字节码方面有深入的了解。同时也可以去生成一个新的类对象,通过完全手动的方式。 由上面的解释也可以看出来这是一个功能强大的类。这里将首先会插入一个最原始的模板类,这个也就是作为我们用来执行命令的恶意类 通过以下这句代码我们就能够获得恶意模板类的对象,通过它我们就能够对该类的结构进行修改 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第15张 然后将为该恶意模板类创建静态代码块,并插入rce的代码 这里rce的代码可以后面自己改,因此也可以自己根据需求定制 接着就是为该类起名字和设置该类的父类为abstranlet 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第16张 接着就是获取该经过加工以后的类的字节码,以字节数组的形式保存,并通过反射的方式来设置templatesImple对象的_bytecodes变量值 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第17张 其中setFieldValue函数第一个参数就是我们要设置的对象,第二个为属性,第三个参数为要设置的值 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第18张 以上就完成了templatesImple的构造和恶意类的构造,但是如果不结合fastjson的反序列化特点的话就要找到一个新的readobject来链接到该templatesImple触发点,我们直接在hashset的readObject的中下断点进行调试,因为最终返回的是linkedHashSet的对象,因此入口点即在HashSet的readObject()函数 这里实际上将hashSet中的对象调用readObject()函数反序列化读出来然后放到有序列表的map中 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第19张 由map.put就即将进入漏洞触发分析,因为后面要用到动态代理。所以这里简单分析一下这个技术: 首先要定义被代理的接口及其实现该接口的子类 接着要定义代理类,需继承自InvocationHandler,也就是位于被代理类处理顺序之前的类,在其构造函数中传入被代理类的对象,当调用被代理类的函数时将触发代理类的invoke函数,此处是重点,通过反射机制来实现 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第20张 定义完被代理类以及代理类之后,还需通过Proxy类将两者进行绑定方可使用,这里要用Proxy.newProxyInstance来创建代理对象,通过其即可完成被代理的类与动态代理的绑定,然后通过该proxy对象就可能对被代理的类的函数进行调用,从而触发动态代理 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第21张 运行结果如下图所示 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第22张 在invoke处下个断点也可以清晰的看到此时method为hello,this.subject为SubjectImpl对象,args为world,即通过为被代理类绑定代理将可以在代理中运行新的代码块 了解了动态代理技术之后,就可以顺理成章地引入AnnotationInvocationHandler了,它就是一个动态代理,其继承自InvocationHandler 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第23张 在其构造函数中有两个成员变量,两个均可控,并且在yso的payload中也通过反射机制为其this.type赋值为Templates类,并在newInstance中为memberValues赋值为只有一个键为f5a5a608,值为foo的map,当然后面将会对该键对应的值进行覆盖,放入恶意templatesImpl的对象,至于为什么要这样赋值后面说 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第24张 目前我们只要知道这里是让AnnotationInvocationHandler作为Templates接口的代理。回到yso的paylaod,继续往下看,这里在linkedhashset中放了两个对象,其中linkedhashset是继承自hashset类的,放入的元素第一个是恶意的templateImpl,第二个是已经绑定了代理的对象 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第25张 那么因为这里为了调试我们之前已经直接在hashset的readobject处下过断点 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第26张 此时第一次反序列化得到的即为放入的恶意templateImpl类的对象,然后将其放到map中 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第27张 第二次反序列化得到的即为proxy对象,为Templates类,这里的map.put即使新的入口点 跟进map.put看看,我们知道一个Map中不能包含相同的key,每个key只能映射一个value,那么能不能插入新的值,put内部肯定是有一定的判断逻辑的,那么这里面就包含了动态代理的触发点 put函数首先要对要放入的key计算一个hash,此时key为proxy对象,跟进此函数看看 其将会调用key.hashCode函数,那么我们知道当调用proxy对象的函数时将触发动态代理类的invoke函数,因此此时此时从下图①或②中都能够看到已经成功通过proxy对象进入到动态代理类AnnotationInvocationHandler当中 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第28张 此时判断我们调用的是hashcode函数,将会进一步调用hashCodeImpl函数 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第29张 在这个函数内部才是真正对map的key进行一个hash的计算 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第30张 这里实际上将用127乘对AnnotationInvocationHandler的memberValues的键计算的hash以及值计算的hash,那么之前我们分析yso的payload时知道赋值给membervalue的键为键为f5a5a608,值为恶意的templateImpl对象,那么此时这个循环将执行一次并且计算key的hascode为0,那么实际上var1的值即为membervalue的键对应值的hascode,其值为恶意的TemplatesImpl对象 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第31张 此时计算得到的hash为106298691,那么为什么要这么设置呢,之后就可以明白 计算完的hash还要经过移位操作然后得到最终的hash值为104622798 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第32张 回到map.put函数的if判断,那么此时e.hash就是计算map第一个键的hash,而map第一个键就是恶意的TemplatesImpl对象,因此计算其hash肯定为104622798 所以之所以yso的payload要这么设置正是因为如此,也就是map的键为什么要设置为f5a5a608的原因,继续往下看 这里用Entry来对要放入的map的中的键进行遍历,其Map.Entry是Map声明的一个内部接口,此接口为泛型,定义为Entry<K,V>,它表示Map中的一个实体(一个key-value对),接着看这个判断: 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第33张 其中有&&连接两部分 ① e.hash == hash ② ((k = e.key) == key || key.equals(k)) 那么此时先理清key和k都是什么,这里的key和k如下图所示,这里的key就是Templates类型的proxy对象,k就是之前第一次放入map中的恶意的Templates对象,此时作为equals函数的入口参数,实际上调用的被代理对象的equals方法,那么这里正和我们的思路,那么想要触发动态代理,我们知道e.key是TemplatesImpl的对象,key是Templates类型的proxy对象,那么判断肯定不成立,那么就能够执行或逻辑右边的表达式,那么此时条件①的已经满足,因此直接调用key.equals(k) 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第34张 那么实际上这里就跳又到annotation这里了,就是我们之前设置的动态代理类,直接到invoke函数处,判断调用的是equals函数 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第35张 这里将会又再次跳到equalsImpl函数,其中入口参数var3[0]为传入的TemplateImpl恶意类,继续跟进 此时1处templateImpl肯定不等于annotation并且2处这里this.type在yso的payload中设置为下图所示,通过反射令其type为Templates类 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第36张 所以这里就是判断templateImpl是不是Templates类的对象,因为Templates是TemplatesImpl的父类,那么这肯定为true 注: class.inInstance(obj) 这个对象能不能被转化为这个类 1.一个对象是本身类的一个对象 2.一个对象能被转化为本身类所继承类(父类的父类等)和实现的接口(接口的父接口)强转 3.所有对象都能被Object的强转 4.凡是null有关的都是false ,即class.inInstance(null) 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第37张 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第38张 此时将会调用getMemberMethods()函数,这个函数内部实际上就是返回annotation这个类的type变量对象的类的所有方法,那么这里实际上返回的就是Templates这个类的两个方法了 ①.Transformer newTransformer() ②.Properties getOutputProperties() 接下来就到了最终的漏洞触发点,我感觉叫链接点比较好,在这里通过反射机制来调用newTransformer(),其中var1就是我们之前构造的恶意的TemplatesImpl类 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第39张 这里我们来回顾一下getOutputProperties处,其中下面的newTransformer和上面反射的newTransformer完美的符合在一起 此时由函数调用栈也可以看到此时回到了TemplateImpl这个类中,至此利用链分析结束
阿里白帽大会-红队的踩"坑"之路总结 这次参加阿里白帽大会,对无声的一个师傅的议题印象比较深刻,ppt暂时不知道会不会共享,我个人想做个总结,最近事情一大堆,学习的效率变慢了许多,不能让这些东西一直压着我.XD 飞机刚起飞,希望到家之前能够写完. 小灰师傅说:"这次由于时间问题,还有很多好玩的没分享出来." 我:"Tql" 以下内容属于我个人YY. 前言 现在各种议题数不胜数,但是我看对眼的比较少. 红队的特点是什么? 区别于传统的渗透测试,更偏向于实战,面对的场景也更加复杂,技术繁多,以目的为导向,需要有能够解决突发问题的能力. 红队的核心是什么? 发散思维,让各种技术有应用场景,需要有更多的攻击面,掌握特殊技巧. 红队之路是什么? 在实践中不断地"

3.从jdk7u25和jdk7u21的对比中分析修复

jdk7u25是jdk7u21的后一个版本,运行后结果如下图所示 那么上面分析的利用AnnotationInvocationHandler作为动态代理打到newTransformer在jdk7u25中已经被修复,运行时将会报错如上图所示,其中是在反序列化的过程中有一步是通过反射机制调用了AnnotationInvocationHandler的readObject函数 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第40张 我们知道在yso的payload中通过反射机制来给AnnotationInvocationHandler的type赋值为Templates类 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第41张 那么再次执行下图代码: 当执行hashset中第二个proxy对象的readObject时,实际上将会在其中调用AnnotationInvocationHandler的readObject函数来恢复动态代理,最终到readObject函数处 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第42张 此时的type为javax.xml.transform.Templates,进一步调用AnnotationType.getInstance 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第43张 跟进看看getInstance函数 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第44张 此时进一步调用Templates.getAnnotationType()函数 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第45张 此时返回为null,继续返回getInstance中 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第46张 此时var1为null,那么将Templates实例传入Annotationtype的构造函数 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第47张 此时在AnnotationType的构造函数将调用isAnnotation对var1进行判断 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第48张 那么明显Templates类跟annotation没关系,可以看到annotation和其他两种数据类型就是java类类型里面定义的,属于class类,即引用数据类型。比如最常见的枚举,枚举类型是Java 5中新增特性的一部分,它是一种特殊的数据类型,之所以特殊是因为它既是一种类(class)类型却又比类类型多了些特殊的约束,但是这些约束的存在也造就了枚举类型的简洁性、安全性以及便捷性。这里实际getModifiers()就是取Templates的修饰符,而Templates是接口类型的,所以两者无关,所以二进制位不可能有所重合,即肯定&&后为0。 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第49张 所以此处必定进入if抛出错误 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第50张 所以回到AnnotationInvocationHandler的readObject中将捕获到该错误从而抛出Non-annotation type in annotation serial stream 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第51张 再回到jdk7u21里面,我们可以看到这里虽然在annotationtype中也捕获到了type不满足条件,并抛出了错误 但是catch以后直接retuen了,并没有再次抛出错误,让上层捕获,因此流程将继续走下去 从0到1掌握某Json-TemplatesImpl链与ysoserial-jdk7u21的前因后果  安全技术 漏洞分析 第52张 所以反序列化将会继续执行,并且能够恢复我们的动态代理Templates,感觉是个逻辑错误,开发人员可能一不注意就会犯错,要发现这些点对于安全研究人员来说开发技能也是必备的。

总结

前前后后分析下来也花了几个晚上,真是学到了不少。整个漏洞利用中包含了很多java中的技术点,最大的感受就是Java的反射特性真的是太重要了,可以说是无处不在2333。挖掘漏洞需要大量调试和分析,补漏洞在这里抛出一个错误就可以让漏洞消失,当然调试的过程中也更加熟悉了java这门语言。  

网友评论

1条评论
  • 2020-08-12 00:03:50

    Allbet Gamingwww.cd799.com欢迎进入欧博平台网站(Allbet Gaming),Allbet Gaming开放欧博平台网址、欧博注册、欧博APP下载、欧博客户端下载、欧博真人游戏(百家乐)等业务。实在是舍不得移开眼