@@ -24,30 +24,30 @@ public class ObjectInputStreamTransformer implements IClassTransformer {
2424
2525 static final Logger LOGGER = LogManager .getLogger ();
2626 private final Type findType ;
27+ private final Type utilsType ;
2728 private final Type replaceType ;
2829
2930 public ObjectInputStreamTransformer () {
3031 findType = Type .getType (ObjectInputStream .class );
32+ utilsType = ASMHelper .getObjectType ("org.apache.commons.lang3.SerializationUtils" );
3133 replaceType = ASMHelper .getObjectType ("me.theandrey.objectstream.ObjectInputStreamMock" );
3234 }
3335
3436 @ Override
3537 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 );
3940
40- ClassNode node = ASMHelper .readClass (bytes );
41+ List <MethodNode > unsafeMethods = scanMethods (node );
42+ boolean superCheck = checkSuperClass (node );
4143
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+ }
4348
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 );
4850 }
49-
50- return ASMHelper .writeClass (node , 0 );
5151 }
5252
5353 return bytes ;
@@ -61,6 +61,10 @@ private List<MethodNode> scanMethods(ClassNode node) {
6161 List <MethodNode > found = new ArrayList <>();
6262
6363 for (MethodNode method : node .methods ) {
64+ if (Config .excludeMethods .contains (ASMHelper .className (node ) + '#' + method .name )) {
65+ continue ;
66+ }
67+
6468 ListIterator <AbstractInsnNode > it = method .instructions .iterator ();
6569 boolean foundNew = false ; // Найден оператор NEW
6670
@@ -86,10 +90,52 @@ private List<MethodNode> scanMethods(ClassNode node) {
8690 invoke .owner = replaceType .getInternalName (); // Заглушка
8791 foundNew = false ; // Завершаем замену блока
8892 }
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+ }
89104 }
90105 }
91106 }
92107
93108 return found ;
94109 }
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+ }
95141}
0 commit comments