JAVA反序列化漏洞利用分析系列

1.简介

  • 该系列主要分析各JAVA反序列化漏洞利用链的实际过程,主要用于代码审计。
  • 例如常见的CC链,或者用于入门分析的URLdns链。

2.关于JAVA反序列化的本质

  1. 想要分析JAVA的反序列漏洞,那么首先,也是必须搞明白的是反序列化的本质到底是什么,是针对对象还是类,还是属性或者函数,这些概率需要搞清楚。
  2. 在JAVA反序列化过程中,JVM会根据字节流中的信息查找相应的类定义,并使用该类定义来创建对象实例,然后根据字节流中的信息设置对象的属性值等状态信息。因此,反序列化是针对对象的,而非类本身。
    • 所以我们需要明白我们序列化的类一定是目标系统有定义的类,而不是自己凭空捏造一个类来序列化,这样目标系统是无法反序列化成功的。也就是说我们没办法编写自己的函数直接在目标系统中执行的。
    • 因此反序列化漏洞的实质是通过嵌套编写对象定义属性值来达到执行目标系统中已有的我们想要执行的那个函数。

3.反序列化漏洞利用链分析流程

  • 在以下所有流程中,我们所选取的类必须满足以下两个条件:
    1. 实现了Serializable接口,否则不可进行序列化,就更不存在什么反序列化。
    2. 必须为目标机器程序中存在的类。

3.1.选取执行类

  1. 执行类主要是为了在服务器执行某个操作的目的,例如读文件,写文件(内存码),SSRF,或者直接RCE等。
  2. 最好为一些可以执行任意方法的类,例如一些反射调用的类,动态代理的类,或者加载远程字节码文件的类等。

3.2.分析调用链

  1. 调用链的目的就是为了连接执行类和入口类,因此我需要通过分析将执行类调用方法通过一步一步的类嵌套,在入口类调用readObject方法时,根据其调用可控对象的方法,最后调用到执行类方法的目的。

3.3.选取入口类

  1. 必须要重写了readObject方法,且在readObject方法中调用了可控参数的方法。
  2. 参数类型尽量宽泛,最好可直接传入Object对象。

4.各利用链分析

  1. URLDNS
  2. CC1-1
  3. CC1-2
  4. CC6
  • 以下是SerializationDumper 工具解析序列化对象的示例
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
STREAM_MAGIC - 0xac ed
STREAM_VERSION - 0x00 05
Contents
TC_OBJECT - 0x73
TC_CLASSDESC - 0x72
className
Length - 24 - 0x00 18
Value - com.gaomu.pojo.ClassDemo - 0x636f6d2e67616f6d752e706f6a6f2e436c61737344656d6f
serialVersionUID - 0xcf 27 61 e5 47 63 3c bd
newHandle 0x00 7e 00 00
classDescFlags - 0x02 - SC_SERIALIZABLE
fieldCount - 4 - 0x00 04
Fields
0:
Int - I - 0x49
fieldName
Length - 5 - 0x00 05
Value - count - 0x636f756e74
1:
Object - L - 0x4c
fieldName
Length - 7 - 0x00 07
Value - mapDemo - 0x6d617044656d6f
className1
TC_STRING - 0x74
newHandle 0x00 7e 00 01
Length - 19 - 0x00 13
Value - Ljava/util/HashMap; - 0x4c6a6176612f7574696c2f486173684d61703b
2:
Object - L - 0x4c
fieldName
Length - 4 - 0x00 04
Value - name - 0x6e616d65
className1
TC_STRING - 0x74
newHandle 0x00 7e 00 02
Length - 18 - 0x00 12
Value - Ljava/lang/String; - 0x4c6a6176612f6c616e672f537472696e673b
3:
Object - L - 0x4c
fieldName
Length - 3 - 0x00 03
Value - obj - 0x6f626a
className1
TC_STRING - 0x74
newHandle 0x00 7e 00 03
Length - 18 - 0x00 12
Value - Ljava/lang/Object; - 0x4c6a6176612f6c616e672f4f626a6563743b
classAnnotations
TC_ENDBLOCKDATA - 0x78
superClassDesc
TC_NULL - 0x70
newHandle 0x00 7e 00 04
classdata
com.gaomu.pojo.ClassDemo
values
count
(int)0 - 0x00 00 00 00
mapDemo
(object)
TC_OBJECT - 0x73
TC_CLASSDESC - 0x72
className
Length - 17 - 0x00 11
Value - java.util.HashMap - 0x6a6176612e7574696c2e486173684d6170
serialVersionUID - 0x05 07 da c1 c3 16 60 d1
newHandle 0x00 7e 00 05
classDescFlags - 0x03 - SC_WRITE_METHOD | SC_SERIALIZABLE
fieldCount - 2 - 0x00 02
Fields
0:
Float - F - 0x46
fieldName
Length - 10 - 0x00 0a
Value - loadFactor - 0x6c6f6164466163746f72
1:
Int - I - 0x49
fieldName
Length - 9 - 0x00 09
Value - threshold - 0x7468726573686f6c64
classAnnotations
TC_ENDBLOCKDATA - 0x78
superClassDesc
TC_NULL - 0x70
newHandle 0x00 7e 00 06
classdata
java.util.HashMap
values
loadFactor
(float)0.75 - 0x3f 40 00 00
threshold
(int)12 - 0x00 00 00 0c
objectAnnotation
TC_BLOCKDATA - 0x77
Length - 8 - 0x08
Contents - 0x0000001000000001
TC_STRING - 0x74
newHandle 0x00 7e 00 07
Length - 5 - 0x00 05
Value - admin - 0x61646d696e
TC_STRING - 0x74
newHandle 0x00 7e 00 08
Length - 6 - 0x00 06
Value - passwd - 0x706173737764
TC_ENDBLOCKDATA - 0x78
name
(object)
TC_STRING - 0x74
newHandle 0x00 7e 00 09
Length - 4 - 0x00 04
Value - DEMO - 0x44454d4f
obj
(object)
TC_OBJECT - 0x73
TC_CLASSDESC - 0x72
className
Length - 19 - 0x00 13
Value - com.gaomu.pojo.User - 0x636f6d2e67616f6d752e706f6a6f2e55736572
serialVersionUID - 0x05 07 91 ff 31 b3 5f 91
newHandle 0x00 7e 00 0a
classDescFlags - 0x02 - SC_SERIALIZABLE
fieldCount - 6 - 0x00 06
Fields
0:
Int - I - 0x49
fieldName
Length - 3 - 0x00 03
Value - age - 0x616765
1:
Object - L - 0x4c
fieldName
Length - 8 - 0x00 08
Value - password - 0x70617373776f7264
className1
TC_REFERENCE - 0x71
Handle - 8257538 - 0x00 7e 00 02
2:
Object - L - 0x4c
fieldName
Length - 5 - 0x00 05
Value - phone - 0x70686f6e65
className1
TC_REFERENCE - 0x71
Handle - 8257538 - 0x00 7e 00 02
3:
Object - L - 0x4c
fieldName
Length - 3 - 0x00 03
Value - sex - 0x736578
className1
TC_REFERENCE - 0x71
Handle - 8257538 - 0x00 7e 00 02
4:
Object - L - 0x4c
fieldName
Length - 6 - 0x00 06
Value - userId - 0x757365724964
className1
TC_REFERENCE - 0x71
Handle - 8257538 - 0x00 7e 00 02
5:
Object - L - 0x4c
fieldName
Length - 8 - 0x00 08
Value - username - 0x757365726e616d65
className1
TC_REFERENCE - 0x71
Handle - 8257538 - 0x00 7e 00 02
classAnnotations
TC_ENDBLOCKDATA - 0x78
superClassDesc
TC_NULL - 0x70
newHandle 0x00 7e 00 0b
classdata
com.gaomu.pojo.User
values
age
(int)0 - 0x00 00 00 00
password
(object)
TC_NULL - 0x70
phone
(object)
TC_NULL - 0x70
sex
(object)
TC_NULL - 0x70
userId
(object)
TC_NULL - 0x70
username
(object)
TC_NULL - 0x70