@@ -24,30 +24,30 @@ public class ObjectInputStreamTransformer implements IClassTransformer {
24
24
25
25
static final Logger LOGGER = LogManager .getLogger ();
26
26
private final Type findType ;
27
+ private final Type utilsType ;
27
28
private final Type replaceType ;
28
29
29
30
public ObjectInputStreamTransformer () {
30
31
findType = Type .getType (ObjectInputStream .class );
32
+ utilsType = ASMHelper .getObjectType ("org.apache.commons.lang3.SerializationUtils" );
31
33
replaceType = ASMHelper .getObjectType ("me.theandrey.objectstream.ObjectInputStreamMock" );
32
34
}
33
35
34
36
@ Override
35
37
public byte [] transform (String name , String transformedName , @ Nullable byte [] bytes ) {
36
- if (bytes == null || bytes .length == 0 || Config .excludeClass .contains (name )) {
37
- return bytes ;
38
- }
38
+ if (bytes != null && bytes .length > 0 ) {
39
+ ClassNode node = ASMHelper .readClass (bytes );
39
40
40
- ClassNode node = ASMHelper .readClass (bytes );
41
+ List <MethodNode > unsafeMethods = scanMethods (node );
42
+ boolean superCheck = checkSuperClass (node );
41
43
42
- List <MethodNode > unsafeMethods = scanMethods (node );
44
+ if (!unsafeMethods .isEmpty () || superCheck ) {
45
+ for (MethodNode method : unsafeMethods ) {
46
+ LOGGER .warn ("SECURITY ALERT: Detected usage of ObjectInputStream in '{}#{}'" , name , method .name );
47
+ }
43
48
44
- if (!unsafeMethods .isEmpty ()) {
45
- LOGGER .warn ("SECURITY ALERT: Detected usage of ObjectInputStream in class '{}'" , name );
46
- for (MethodNode method : unsafeMethods ) {
47
- LOGGER .warn ("Method: {} {}" , name , method .name + method .desc );
49
+ return ASMHelper .writeClass (node , 0 );
48
50
}
49
-
50
- return ASMHelper .writeClass (node , 0 );
51
51
}
52
52
53
53
return bytes ;
@@ -61,6 +61,10 @@ private List<MethodNode> scanMethods(ClassNode node) {
61
61
List <MethodNode > found = new ArrayList <>();
62
62
63
63
for (MethodNode method : node .methods ) {
64
+ if (Config .excludeMethods .contains (ASMHelper .className (node ) + '#' + method .name )) {
65
+ continue ;
66
+ }
67
+
64
68
ListIterator <AbstractInsnNode > it = method .instructions .iterator ();
65
69
boolean foundNew = false ; // Найден оператор NEW
66
70
@@ -86,10 +90,52 @@ private List<MethodNode> scanMethods(ClassNode node) {
86
90
invoke .owner = replaceType .getInternalName (); // Заглушка
87
91
foundNew = false ; // Завершаем замену блока
88
92
}
93
+
94
+ } else if (next .getOpcode () == Opcodes .INVOKESTATIC ) {
95
+ MethodInsnNode invoke = ((MethodInsnNode )next );
96
+
97
+ if ("deserialize" .equals (invoke .name ) && invoke .owner .equals (utilsType .getInternalName ())) {
98
+ invoke .owner = replaceType .getInternalName (); // Заглушка
99
+
100
+ if (!found .contains (method )) {
101
+ found .add (method );
102
+ }
103
+ }
89
104
}
90
105
}
91
106
}
92
107
93
108
return found ;
94
109
}
110
+
111
+ private boolean checkSuperClass (ClassNode node ) {
112
+ String name = ASMHelper .className (node );
113
+ if (!Config .excludeClass .contains (name ) && node .superName .equals (findType .getInternalName ())) {
114
+ node .superName = replaceType .getInternalName ();
115
+
116
+ // Замена вызова конструктора родителя
117
+ for (MethodNode method : node .methods ) {
118
+ if (method .name .equals ("<init>" )) {
119
+ ListIterator <AbstractInsnNode > it = method .instructions .iterator ();
120
+
121
+ while (it .hasNext ()) {
122
+ AbstractInsnNode next = it .next ();
123
+
124
+ if (next .getOpcode () == Opcodes .INVOKESPECIAL ) {
125
+ MethodInsnNode invoke = ((MethodInsnNode )next );
126
+
127
+ if ("<init>" .equals (invoke .name ) && invoke .owner .equals (findType .getInternalName ())) {
128
+ invoke .owner = replaceType .getInternalName ();
129
+ }
130
+ }
131
+ }
132
+ }
133
+ }
134
+
135
+ LOGGER .warn ("SECURITY ALERT: Detected extending of ObjectInputStream in '{}'" , name );
136
+ return true ;
137
+ }
138
+
139
+ return false ;
140
+ }
95
141
}
0 commit comments