ysoserial分析之FileUpload1利用链

admin 2022年6月10日09:45:11代码审计评论12 views2703字阅读9分0秒阅读模式

0x01 前言

本次漏洞,感觉涉及的知识点不是特别多,只是当作学习笔记,感兴趣的童鞋可以看一看,写得不好的地方,大佬们多多包涵。


0x02 漏洞分析


01 漏洞分析

本漏洞较为简单,所以我自己写了个测试demo,用来调试了解序列化/反序列化的执行过程,仅供学习使用,代码如下

import org.apache.commons.fileupload.disk.DiskFileItem;import org.apache.commons.io.output.DeferredFileOutputStream;import java.io.*;import java.lang.reflect.Field;
public class Demo1 {
public static void main(String[] args) { domain(); }
private static void domain() { byte[] bytes = "abc123".getBytes(); File file = new File("d:/temp1"); try { DeferredFileOutputStream dfos = new DeferredFileOutputStream(3, file); /*Field written = ThresholdingOutputStream.class.getDeclaredField("written"); written.setAccessible(true); written.set(dfos, 2);*/
DiskFileItem disk = new DiskFileItem(null, null, false, null, 0, file); Field dfos1 = disk.getClass().getDeclaredField("dfos"); dfos1.setAccessible(true); dfos1.set(disk, dfos);
Field cachedContent = disk.getClass().getDeclaredField("cachedContent"); cachedContent.setAccessible(true); cachedContent.set(disk, bytes);
ByteArrayOutputStream baos1 = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos1); oos.writeObject(disk);
ByteArrayInputStream bais = new ByteArrayInputStream(baos1.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bais); ois.readObject(); } catch (IOException | IllegalAccessException | NoSuchFieldException | ClassNotFoundException e) { e.printStackTrace(); } }}



我们在 org.apache.commons.fileupload.disk.DiskFileItem#writeObject 和 org.apache.commons.fileupload.disk.DiskFileItem#readObject方法处打上断点,留作调试

ysoserial分析之FileUpload1利用链


这个应该没什么要说的,定义了一个字节数组,new了一个file对象,将file对象作为 DeferredFileOutputStream 构造方法参数传入,其中第一个参数随便给,后面会讲到,这里我注释了三行,这里是为了给 written字段赋值,后面也会解释,赋不赋值其实都是一样的,接着往下走

ysoserial分析之FileUpload1利用链

ysoserial分析之FileUpload1利用链


这里是实例化了一个 DiskFileItem 对象,主要是最后一个参数,其他参数可以忽略,然后通过反射的方式,将disk对象的dfos字段赋值为我们定义的dfos对象 ,接着往下走

ysoserial分析之FileUpload1利用链


通过反射获取到disk对象的 cacheContent 字段,并赋值为我们自定义的内容 ,继续往下

ysoserial分析之FileUpload1利用链


将disk对象序列化写入ByteArrayOutputStream,触发writeObject方法,跟入

ysoserial分析之FileUpload1利用链


调用 this.dfos.isInMemory() 方法,跟入

ysoserial分析之FileUpload1利用链


看到调用 this.isThresholdExceeded() 方法,并对结果进行取反,跟入

ysoserial分析之FileUpload1利用链


这里由于我们没有定义written,所以默认值为0,而 threshold 我们初始赋值为3,这里应该 为false,取反后为true,回到 org.apache.commons.fileupload.disk.DiskFileItem#writeObject 方法

ysoserial分析之FileUpload1利用链


跟入

ysoserial分析之FileUpload1利用链


跟入 this.isInMemory() ,如图

ysoserial分析之FileUpload1利用链


很显然cachedContent不为null,所以返回true,然后直接返回 cachedContent,至此 writeObject 调用结束

我们回到readObject方法,如图

ysoserial分析之FileUpload1利用链


跟入

ysoserial分析之FileUpload1利用链


这里可以看到dfos为null,这是为什么呢,前面不是反射赋值过了吗,我们来看一下该字段的修饰符

ysoserial分析之FileUpload1利用链


看到transient大家就应该明白了,该字段不可被反序列化,所以反序列化之后他的状态没有保存下来,这也是为什么只能写入临时文件的原因,如果该字段不是transient的话,应该是可以任意目录写入任意文件的,继续往下

ysoserial分析之FileUpload1利用链


调用getTempFile方法创建临时文件,目录使用我们传入的目录,这就导致了文件名不可控的问题,最后将返回的file对象传入 DeferredFileOutputStream 构造方法,并返回,回到 org.apache.commons.fileupload.disk.DiskFileItem#readObject 继续往下走

ysoserial分析之FileUpload1利用链

这里因为 cachedContent 是我们自定义的内容,不为null,所以直接调用写入,我们还可以看到如果cachedContent 为null的话,会进入else代码块,这时会将 this.dfosFile 文件内容复制给生成的临时文件,然后删除 this.dfosFile 文件,这也就是另一个利用方式了,聪明的你们应该不用我说了吧,文件写入和删除其实都很简单,就是对应字段赋值然后反序列化触发

生成的临时文件长这样

ysoserial分析之FileUpload1利用链


0x03 总结

本漏洞其实没有太多可讲的知识点,也可能是本人理解不深,希望对感兴趣的童鞋能给到一定的学习帮助,我们一起进步成长。


原文始发于微信公众号(伟盾网络安全):ysoserial分析之FileUpload1利用链

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年6月10日09:45:11
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  ysoserial分析之FileUpload1利用链 http://cn-sec.com/archives/1097896.html

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: