From a2f01fde77f327c16ad43316f72d6c125aaec841 Mon Sep 17 00:00:00 2001 From: tscuitego <64051240+tscuite@users.noreply.github.com> Date: Tue, 7 Mar 2023 12:18:57 +0800 Subject: [PATCH 1/7] feat: add beat deploy --- .github/workflows/code-check.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/code-check.yml b/.github/workflows/code-check.yml index 219fea1d3..a25172bdd 100644 --- a/.github/workflows/code-check.yml +++ b/.github/workflows/code-check.yml @@ -5,9 +5,9 @@ name: Build Agent and Upload To OSS on: push: - branches: [ main ] + branches: [ beta ] pull_request: - branches: [ main ] + branches: [ beta ] paths-ignore: - '.github/**' - 'changes/**' From 960d8f281fbd0c7ce17dc8150647f987d16ae01f Mon Sep 17 00:00:00 2001 From: lostsnow Date: Wed, 1 Mar 2023 11:22:43 +0800 Subject: [PATCH 2/7] add dubbo consumer invoke track --- .../core/bytecode/enhance/asm/AsmMethods.java | 16 ++- .../enhance/plugin/PluginRegister.java | 2 + .../plugin/framework/dubbo/DispatchDubbo.java | 21 ++++ .../dubbo/LegacyDubboSyncHandlerAdapter.java | 29 +++++ ...cyDubboSyncHandlerInvokeAdviceAdapter.java | 111 ++++++++++++++++++ .../plugin/framework/feign/DispatchFeign.java | 2 +- .../handler/hookpoint/SpyDispatcherImpl.java | 23 ++++ .../hookpoint/controller/impl/SourceImpl.java | 97 +-------------- .../models/policy/PolicyManager.java | 5 +- .../hookpoint/service/trace/DubboService.java | 56 +++++++++ .../hookpoint/service/trace/FeignService.java | 82 +------------ .../iast/core/utils/TaintPoolUtils.java | 110 +++++++++++++++++ .../main/java/io/dongtai/log/ErrorCode.java | 1 + .../main/java/java/lang/dongtai/NopSpy.java | 10 +- .../java/java/lang/dongtai/SpyDispatcher.java | 7 +- 15 files changed, 393 insertions(+), 179 deletions(-) create mode 100644 dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DispatchDubbo.java create mode 100644 dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboSyncHandlerAdapter.java create mode 100644 dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboSyncHandlerInvokeAdviceAdapter.java create mode 100644 dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/service/trace/DubboService.java diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/asm/AsmMethods.java b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/asm/AsmMethods.java index 8ae4e1c82..29573afbf 100755 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/asm/AsmMethods.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/asm/AsmMethods.java @@ -4,8 +4,7 @@ import java.lang.dongtai.SpyDispatcher; import java.lang.dongtai.SpyDispatcherHandler; -import java.util.Collection; -import java.util.Enumeration; +import java.util.*; /** * 常用的ASM method 集合 省得我到处声明 @@ -209,6 +208,19 @@ static Method getAsmMethod(final Class clazz, String.class ); + Method SPY$traceDubboInvoke = InnerHelper.getAsmMethod( + SpyDispatcher.class, + "traceDubboInvoke", + Object.class, + String.class, + Object.class, + Object[].class, + Map.class, + String.class, + String.class, + String.class + ); + Method SPY$reportService = InnerHelper.getAsmMethod( SpyDispatcher.class, "reportService", diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/PluginRegister.java b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/PluginRegister.java index f9eb37475..63d60da6b 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/PluginRegister.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/PluginRegister.java @@ -3,6 +3,7 @@ import io.dongtai.iast.core.bytecode.enhance.ClassContext; import io.dongtai.iast.core.bytecode.enhance.plugin.authentication.shiro.DispatchShiro; import io.dongtai.iast.core.bytecode.enhance.plugin.core.DispatchClassPlugin; +import io.dongtai.iast.core.bytecode.enhance.plugin.framework.dubbo.DispatchDubbo; import io.dongtai.iast.core.bytecode.enhance.plugin.framework.feign.DispatchFeign; import io.dongtai.iast.core.bytecode.enhance.plugin.framework.j2ee.dispatch.DispatchJ2ee; import io.dongtai.iast.core.bytecode.enhance.plugin.hardcoded.DispatchHardcodedPlugin; @@ -34,6 +35,7 @@ public PluginRegister() { this.plugins.add(new DispatchJdbc()); this.plugins.add(new DispatchShiro()); this.plugins.add(new DispatchFeign()); + this.plugins.add(new DispatchDubbo()); this.plugins.add(new DispatchClassPlugin()); } diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DispatchDubbo.java b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DispatchDubbo.java new file mode 100644 index 000000000..b20445ee0 --- /dev/null +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DispatchDubbo.java @@ -0,0 +1,21 @@ +package io.dongtai.iast.core.bytecode.enhance.plugin.framework.dubbo; + +import io.dongtai.iast.core.bytecode.enhance.ClassContext; +import io.dongtai.iast.core.bytecode.enhance.plugin.DispatchPlugin; +import io.dongtai.iast.core.handler.hookpoint.models.policy.Policy; +import org.objectweb.asm.ClassVisitor; + +public class DispatchDubbo implements DispatchPlugin { + public static final String LEGACY_DUBBO_SYNC_HANDLER = " com.alibaba.dubbo.rpc.listener.ListenerInvokerWrapper".substring(1); + + @Override + public ClassVisitor dispatch(ClassVisitor classVisitor, ClassContext context, Policy policy) { + String className = context.getClassName(); + + if (LEGACY_DUBBO_SYNC_HANDLER.equals(className)) { + classVisitor = new LegacyDubboSyncHandlerAdapter(classVisitor, context); + } + + return classVisitor; + } +} diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboSyncHandlerAdapter.java b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboSyncHandlerAdapter.java new file mode 100644 index 000000000..60915f050 --- /dev/null +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboSyncHandlerAdapter.java @@ -0,0 +1,29 @@ +package io.dongtai.iast.core.bytecode.enhance.plugin.framework.dubbo; + +import io.dongtai.iast.core.bytecode.enhance.ClassContext; +import io.dongtai.iast.core.bytecode.enhance.plugin.AbstractClassVisitor; +import io.dongtai.iast.core.utils.AsmUtils; +import io.dongtai.log.DongTaiLog; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; + +public class LegacyDubboSyncHandlerAdapter extends AbstractClassVisitor { + private static final String LEGACY_DUBBO_SYNC_HANDLER_INVOKE = " com.alibaba.dubbo.rpc.listener.ListenerInvokerWrapper.invoke(com.alibaba.dubbo.rpc.Invocation)".substring(1); + + public LegacyDubboSyncHandlerAdapter(ClassVisitor classVisitor, ClassContext context) { + super(classVisitor, context); + } + + @Override + public MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) { + MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); + String signCode = AsmUtils.buildSignature(context.getClassName(), name, desc); + + if (LEGACY_DUBBO_SYNC_HANDLER_INVOKE.equals(signCode)) { + DongTaiLog.debug("Adding dubbo tracking by {}", signCode); + mv = new LegacyDubboSyncHandlerInvokeAdviceAdapter(mv, access, name, desc, signCode, this.context); + setTransformed(); + } + return mv; + } +} diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboSyncHandlerInvokeAdviceAdapter.java b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboSyncHandlerInvokeAdviceAdapter.java new file mode 100644 index 000000000..161d09c06 --- /dev/null +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboSyncHandlerInvokeAdviceAdapter.java @@ -0,0 +1,111 @@ +package io.dongtai.iast.core.bytecode.enhance.plugin.framework.dubbo; + +import io.dongtai.iast.core.bytecode.enhance.ClassContext; +import io.dongtai.iast.core.bytecode.enhance.plugin.AbstractAdviceAdapter; +import org.objectweb.asm.*; +import org.objectweb.asm.commons.Method; + +public class LegacyDubboSyncHandlerInvokeAdviceAdapter extends AbstractAdviceAdapter { + private static final Method GET_URL_METHOD = Method.getMethod(" com.alibaba.dubbo.common.URL getUrl()".substring(1)); + private static final Method GET_ARGUMENTS_METHOD = Method.getMethod("java.lang.Object[] getArguments()"); + private static final Method GET_GETATTACHMENTS_METHOD = Method.getMethod("java.util.Map getAttachments()"); + private static final Method URL_TO_STRING_METHOD = Method.getMethod("java.lang.String toString()"); + + private Label exHandler; + private final Type handlerType; + private final Type urlType; + private final Type invocationType; + + protected LegacyDubboSyncHandlerInvokeAdviceAdapter(MethodVisitor mv, int access, String name, String desc, String signature, ClassContext context) { + super(mv, access, name, desc, context, "dubbo", signature); + this.handlerType = Type.getObjectType(" com/alibaba/dubbo/rpc/listener/ListenerInvokerWrapper".substring(1)); + this.invocationType = Type.getObjectType(" com/alibaba/dubbo/rpc/Invocation".substring(1)); + this.urlType = Type.getObjectType(" com/alibaba/dubbo/common/URL".substring(1)); + } + + @Override + protected void onMethodEnter() { + this.tryLabel = new Label(); + visitLabel(this.tryLabel); + enterMethod(); + this.catchLabel = new Label(); + this.exHandler = new Label(); + } + + @Override + protected void onMethodExit(int opcode) { + leaveMethod(opcode); + } + + @Override + protected void before() { + } + + @Override + protected void after(int opcode) { + } + + @Override + public void visitMaxs(int maxStack, int maxLocals) { + visitLabel(this.catchLabel); + visitLabel(this.exHandler); + leaveMethod(ATHROW); + throwException(); + visitTryCatchBlock(this.tryLabel, this.catchLabel, this.exHandler, ASM_TYPE_THROWABLE.getInternalName()); + super.visitMaxsNew(maxStack, maxLocals); + } + + private void enterMethod() { + enterScope(); + + Label elseLabel = new Label(); + Label endLabel = new Label(); + + isFirstScope(); + mv.visitJumpInsn(Opcodes.IFEQ, elseLabel); + + traceMethod(); + + mark(elseLabel); + mark(endLabel); + } + + private void leaveMethod(int opcode) { + leaveScope(); + } + + private void enterScope() { + invokeStatic(ASM_TYPE_SPY_HANDLER, SPY_HANDLER$getDispatcher); + push(false); + invokeInterface(ASM_TYPE_SPY_DISPATCHER, SPY$enterPropagator); + } + + private void leaveScope() { + invokeStatic(ASM_TYPE_SPY_HANDLER, SPY_HANDLER$getDispatcher); + push(false); + invokeInterface(ASM_TYPE_SPY_DISPATCHER, SPY$leavePropagator); + } + + private void isFirstScope() { + invokeStatic(ASM_TYPE_SPY_HANDLER, SPY_HANDLER$getDispatcher); + invokeInterface(ASM_TYPE_SPY_DISPATCHER, SPY$isFirstLevelPropagator); + } + + private void traceMethod() { + invokeStatic(ASM_TYPE_SPY_HANDLER, SPY_HANDLER$getDispatcher); + loadThisOrPushNullIfIsStatic(); + dup(); + invokeVirtual(this.handlerType, GET_URL_METHOD); + invokeVirtual(this.urlType, URL_TO_STRING_METHOD); + loadArg(0); + loadArg(0); + invokeInterface(this.invocationType, GET_ARGUMENTS_METHOD); + loadArg(0); + invokeInterface(this.invocationType, GET_GETATTACHMENTS_METHOD); + push(this.classContext.getClassName()); + push(this.name); + push(this.signature); + invokeInterface(ASM_TYPE_SPY_DISPATCHER, SPY$traceDubboInvoke); + pop(); + } +} diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/feign/DispatchFeign.java b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/feign/DispatchFeign.java index 88b53066d..35cae7a26 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/feign/DispatchFeign.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/feign/DispatchFeign.java @@ -6,7 +6,7 @@ import org.objectweb.asm.ClassVisitor; public class DispatchFeign implements DispatchPlugin { - private static final String FEIGN_SYNC_HANDLER = "feign.SynchronousMethodHandler"; + public static final String FEIGN_SYNC_HANDLER = "feign.SynchronousMethodHandler"; @Override public ClassVisitor dispatch(ClassVisitor classVisitor, ClassContext context, Policy policy) { diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/SpyDispatcherImpl.java b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/SpyDispatcherImpl.java index 38e99f9dc..adec8ce7d 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/SpyDispatcherImpl.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/SpyDispatcherImpl.java @@ -11,6 +11,7 @@ import io.dongtai.iast.core.handler.hookpoint.graphy.GraphBuilder; import io.dongtai.iast.core.handler.hookpoint.models.MethodEvent; import io.dongtai.iast.core.handler.hookpoint.models.policy.*; +import io.dongtai.iast.core.handler.hookpoint.service.trace.DubboService; import io.dongtai.iast.core.handler.hookpoint.service.trace.FeignService; import io.dongtai.iast.core.utils.StringUtils; import io.dongtai.log.DongTaiLog; @@ -535,6 +536,28 @@ public boolean traceFeignInvoke(Object instance, Object[] parameters, return false; } + @Override + public boolean traceDubboInvoke(Object instance, String url, Object invocation, Object[] arguments, + Map headers, String className, String methodName, + String signature) { + try { + ScopeManager.SCOPE_TRACKER.getPolicyScope().enterAgent(); + if (!isCollectAllowed(false)) { + return false; + } + + MethodEvent event = new MethodEvent(className, className, methodName, + signature, instance, arguments, null); + + DubboService.solveSyncInvoke(event, invocation, url, headers, INVOKE_ID_SEQUENCER); + } catch (Throwable e) { + DongTaiLog.error(ErrorCode.SPY_TRACE_DUBBO_INVOKE_FAILED, e); + } finally { + ScopeManager.SCOPE_TRACKER.getPolicyScope().leaveAgent(); + } + return false; + } + @SuppressWarnings("unchecked") private boolean isCollectAllowed(boolean isEnterEntry) { if (!EngineManager.isEngineRunning()) { diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/controller/impl/SourceImpl.java b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/controller/impl/SourceImpl.java index 75901b9fb..33ace410e 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/controller/impl/SourceImpl.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/controller/impl/SourceImpl.java @@ -4,12 +4,12 @@ import io.dongtai.iast.core.handler.hookpoint.models.MethodEvent; import io.dongtai.iast.core.handler.hookpoint.models.policy.SourceNode; import io.dongtai.iast.core.handler.hookpoint.models.policy.TaintPosition; -import io.dongtai.iast.core.handler.hookpoint.models.taint.range.*; +import io.dongtai.iast.core.handler.hookpoint.models.taint.range.TaintRangesBuilder; import io.dongtai.iast.core.utils.StackUtils; import io.dongtai.iast.core.utils.TaintPoolUtils; -import java.lang.reflect.Array; -import java.util.*; +import java.util.ArrayList; +import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; /** @@ -81,99 +81,12 @@ private static boolean trackTarget(MethodEvent event, SourceNode sourceNode) { return false; } - trackObject(event, sourceNode, event.returnInstance, 0); + TaintPoolUtils.trackObject(event, sourceNode, event.returnInstance, 0); // @TODO: hook json serializer for custom model handlerCustomModel(event, sourceNode); return true; } - private static void trackObject(MethodEvent event, SourceNode sourceNode, Object obj, int depth) { - if (depth >= 10 || !TaintPoolUtils.isNotEmpty(obj) || !TaintPoolUtils.isAllowTaintType(obj)) { - return; - } - - int hash = System.identityHashCode(obj); - if (EngineManager.TAINT_HASH_CODES.contains(hash)) { - return; - } - - Class cls = obj.getClass(); - if (cls.isArray() && !cls.getComponentType().isPrimitive()) { - trackArray(event, sourceNode, obj, depth); - } else if (obj instanceof Iterator && !(obj instanceof Enumeration)) { - trackIterator(event, sourceNode, (Iterator) obj, depth); - } else if (obj instanceof Map) { - trackMap(event, sourceNode, (Map) obj, depth); - } else if (obj instanceof Map.Entry) { - trackMapEntry(event, sourceNode, (Map.Entry) obj, depth); - } else if (obj instanceof Collection) { - if (obj instanceof List) { - trackList(event, sourceNode, (List) obj, depth); - } else { - trackIterator(event, sourceNode, ((Collection) obj).iterator(), depth); - } - } else if ("java.util.Optional".equals(obj.getClass().getName())) { - trackOptional(event, sourceNode, obj, depth); - } else { - int len = TaintRangesBuilder.getLength(obj); - if (len == 0) { - return; - } - - TaintRanges tr = new TaintRanges(new TaintRange(0, len)); - if (sourceNode.hasTags()) { - String[] tags = sourceNode.getTags(); - for (String tag : tags) { - tr.add(new TaintRange(tag, 0, len)); - } - } - event.targetRanges.add(new MethodEvent.MethodEventTargetRange(hash, tr)); - - EngineManager.TAINT_HASH_CODES.add(hash); - event.addTargetHash(hash); - EngineManager.TAINT_RANGES_POOL.add(hash, tr); - } - } - - private static void trackArray(MethodEvent event, SourceNode sourceNode, Object arr, int depth) { - int length = Array.getLength(arr); - for (int i = 0; i < length; i++) { - trackObject(event, sourceNode, Array.get(arr, i), depth + 1); - } - } - - private static void trackIterator(MethodEvent event, SourceNode sourceNode, Iterator it, int depth) { - while (it.hasNext()) { - trackObject(event, sourceNode, it.next(), depth + 1); - } - } - - private static void trackMap(MethodEvent event, SourceNode sourceNode, Map map, int depth) { - for (Object key : map.keySet()) { - trackObject(event, sourceNode, key, depth + 1); - trackObject(event, sourceNode, map.get(key), depth + 1); - } - } - - private static void trackMapEntry(MethodEvent event, SourceNode sourceNode, Map.Entry entry, int depth) { - trackObject(event, sourceNode, entry.getKey(), depth + 1); - trackObject(event, sourceNode, entry.getValue(), depth + 1); - } - - private static void trackList(MethodEvent event, SourceNode sourceNode, List list, int depth) { - for (Object obj : list) { - trackObject(event, sourceNode, obj, depth + 1); - } - } - - private static void trackOptional(MethodEvent event, SourceNode sourceNode, Object obj, int depth) { - try { - Object v = ((Optional) obj).orElse(null); - trackObject(event, sourceNode, v, depth + 1); - } catch (Throwable ignore) { - } - } - /** * todo: 处理过程和结果需要细化 * @@ -183,7 +96,7 @@ public static void handlerCustomModel(MethodEvent event, SourceNode sourceNode) if (!"getSession".equals(event.getMethodName())) { Set modelValues = TaintPoolUtils.parseCustomModel(event.returnInstance); for (Object modelValue : modelValues) { - trackObject(event, sourceNode, modelValue, 0); + TaintPoolUtils.trackObject(event, sourceNode, modelValue, 0); } } } diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/models/policy/PolicyManager.java b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/models/policy/PolicyManager.java index 96fea6e15..3624c1329 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/models/policy/PolicyManager.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/models/policy/PolicyManager.java @@ -1,5 +1,7 @@ package io.dongtai.iast.core.handler.hookpoint.models.policy; +import io.dongtai.iast.core.bytecode.enhance.plugin.framework.dubbo.DispatchDubbo; +import io.dongtai.iast.core.bytecode.enhance.plugin.framework.feign.DispatchFeign; import io.dongtai.iast.core.bytecode.enhance.plugin.framework.j2ee.dispatch.DispatchJ2ee; import io.dongtai.iast.core.utils.StringUtils; import io.dongtai.log.DongTaiLog; @@ -27,7 +29,8 @@ public class PolicyManager { " org.springframework.web.servlet.FrameworkServlet".substring(1), " javax.servlet.http.Cookie".substring(1), " org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker".substring(1), - " feign.SynchronousMethodHandler.invoke".substring(1) + DispatchFeign.FEIGN_SYNC_HANDLER, + DispatchDubbo.LEGACY_DUBBO_SYNC_HANDLER )); private static final Set HOOK_CLASS_SUFFIX_NAMES = new HashSet(Collections.singletonList( ".dubbo.monitor.support.MonitorFilter" diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/service/trace/DubboService.java b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/service/trace/DubboService.java new file mode 100644 index 000000000..8293826bb --- /dev/null +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/service/trace/DubboService.java @@ -0,0 +1,56 @@ +package io.dongtai.iast.core.handler.hookpoint.service.trace; + +import io.dongtai.iast.core.EngineManager; +import io.dongtai.iast.core.handler.context.ContextManager; +import io.dongtai.iast.core.handler.hookpoint.models.MethodEvent; +import io.dongtai.iast.core.utils.StackUtils; +import io.dongtai.iast.core.utils.TaintPoolUtils; +import io.dongtai.log.DongTaiLog; + +import java.lang.reflect.Method; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; + +public class DubboService { + public static void solveSyncInvoke(MethodEvent event, Object invocation, String url, Map headers, + AtomicInteger invokeIdSequencer) { + try { + TaintPoolUtils.trackObject(event, null, event.parameterInstances, 0); + boolean hasTaint = false; + int sourceLen = 0; + if (!event.getSourceHashes().isEmpty()) { + hasTaint = true; + sourceLen = event.getSourceHashes().size(); + } + event.addParameterValue(0, event.parameterInstances, hasTaint); + + if (headers != null && headers.size() > 0) { + hasTaint = false; + TaintPoolUtils.trackObject(event, null, headers, 0); + if (event.getSourceHashes().size() > sourceLen) { + hasTaint = true; + } + event.addParameterValue(1, headers, hasTaint); + } + + Method setAttachmentMethod = invocation.getClass().getMethod("setAttachment", String.class, String.class); + setAttachmentMethod.setAccessible(true); + String traceId = ContextManager.nextTraceId(); + setAttachmentMethod.invoke(invocation, ContextManager.getHeaderKey(), traceId); + + // add to method pool + event.source = false; + event.traceId = traceId; + event.setCallStacks(StackUtils.createCallStack(4)); + int invokeId = invokeIdSequencer.getAndIncrement(); + event.setInvokeId(invokeId); + EngineManager.TRACK_MAP.get().put(invokeId, event); + } catch (NoSuchMethodException ignore) { + } catch (Throwable e) { + DongTaiLog.debug("solve dubbo invoke failed: {}, {}", + e.getMessage(), e.getCause() != null ? e.getCause().getMessage() : ""); + } + } + + +} diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/service/trace/FeignService.java b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/service/trace/FeignService.java index 7d450b0f1..2d9e3e002 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/service/trace/FeignService.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/service/trace/FeignService.java @@ -7,8 +7,8 @@ import io.dongtai.iast.core.utils.TaintPoolUtils; import io.dongtai.log.DongTaiLog; -import java.lang.reflect.*; -import java.util.*; +import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.util.concurrent.atomic.AtomicInteger; public class FeignService { @@ -27,7 +27,7 @@ public static void solveSyncInvoke(MethodEvent event, AtomicInteger invokeIdSequ // get args Object args = event.parameterInstances[0]; - trackObject(event, args, 0); + TaintPoolUtils.trackObject(event, null, args, 0); boolean hasTaint = false; if (!event.getSourceHashes().isEmpty()) { @@ -59,80 +59,4 @@ public static void solveSyncInvoke(MethodEvent event, AtomicInteger invokeIdSequ e.getMessage(), e.getCause() != null ? e.getCause().getMessage() : ""); } } - - private static void trackObject(MethodEvent event, Object obj, int depth) { - if (depth >= 10 || !TaintPoolUtils.isNotEmpty(obj) || !TaintPoolUtils.isAllowTaintType(obj)) { - return; - } - - Class cls = obj.getClass(); - if (cls.isArray() && !cls.getComponentType().isPrimitive()) { - trackArray(event, obj, depth); - } else if (obj instanceof Iterator) { - trackIterator(event, (Iterator) obj, depth); - } else if (obj instanceof Map) { - trackMap(event, (Map) obj, depth); - } else if (obj instanceof Map.Entry) { - trackMapEntry(event, (Map.Entry) obj, depth); - } else if (obj instanceof Collection) { - if (obj instanceof List) { - trackList(event, (List) obj, depth); - } else { - trackIterator(event, ((Collection) obj).iterator(), depth); - } - } else if ("java.util.Optional".equals(obj.getClass().getName())) { - trackOptional(event, obj, depth); - } else { - if (!(obj instanceof String)) { - Set modelValues = TaintPoolUtils.parseCustomModel(obj); - for (Object modelValue : modelValues) { - trackObject(event, modelValue, depth + 1); - } - } - - int hash = System.identityHashCode(obj); - if (EngineManager.TAINT_HASH_CODES.contains(hash)) { - event.addSourceHash(hash); - } - } - } - - private static void trackArray(MethodEvent event, Object arr, int depth) { - int length = Array.getLength(arr); - for (int i = 0; i < length; i++) { - trackObject(event, Array.get(arr, i), depth + 1); - } - } - - private static void trackIterator(MethodEvent event, Iterator it, int depth) { - while (it.hasNext()) { - trackObject(event, it.next(), depth + 1); - } - } - - private static void trackMap(MethodEvent event, Map map, int depth) { - for (Object key : map.keySet()) { - trackObject(event, key, depth + 1); - trackObject(event, map.get(key), depth + 1); - } - } - - private static void trackMapEntry(MethodEvent event, Map.Entry entry, int depth) { - trackObject(event, entry.getKey(), depth + 1); - trackObject(event, entry.getValue(), depth + 1); - } - - private static void trackList(MethodEvent event, List list, int depth) { - for (Object obj : list) { - trackObject(event, obj, depth + 1); - } - } - - private static void trackOptional(MethodEvent event, Object obj, int depth) { - try { - Object v = ((Optional) obj).orElse(null); - trackObject(event, v, depth + 1); - } catch (Throwable ignore) { - } - } } diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/utils/TaintPoolUtils.java b/dongtai-core/src/main/java/io/dongtai/iast/core/utils/TaintPoolUtils.java index cd8a6f823..6ad0fed28 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/utils/TaintPoolUtils.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/utils/TaintPoolUtils.java @@ -2,9 +2,13 @@ import io.dongtai.iast.core.EngineManager; import io.dongtai.iast.core.handler.hookpoint.models.MethodEvent; +import io.dongtai.iast.core.handler.hookpoint.models.policy.PolicyNode; +import io.dongtai.iast.core.handler.hookpoint.models.policy.SourceNode; +import io.dongtai.iast.core.handler.hookpoint.models.taint.range.*; import io.dongtai.log.DongTaiLog; import io.dongtai.log.ErrorCode; +import java.lang.reflect.Array; import java.lang.reflect.Method; import java.math.BigDecimal; import java.util.*; @@ -252,4 +256,110 @@ public static boolean isAllowTaintGetterMethod(Method method) { return isAllowTaintType(method.getReturnType()); } + + public static void trackObject(MethodEvent event, PolicyNode policyNode, Object obj, int depth) { + if (depth >= 10 || !TaintPoolUtils.isNotEmpty(obj) || !TaintPoolUtils.isAllowTaintType(obj)) { + return; + } + + int hash = 0; + boolean isSourceNode = policyNode instanceof SourceNode; + if (isSourceNode) { + hash = System.identityHashCode(obj); + if (EngineManager.TAINT_HASH_CODES.contains(hash)) { + return; + } + } + + Class cls = obj.getClass(); + if (cls.isArray() && !cls.getComponentType().isPrimitive()) { + trackArray(event, policyNode, obj, depth); + } else if (obj instanceof Iterator && !(obj instanceof Enumeration)) { + trackIterator(event, policyNode, (Iterator) obj, depth); + } else if (obj instanceof Map) { + trackMap(event, policyNode, (Map) obj, depth); + } else if (obj instanceof Map.Entry) { + trackMapEntry(event, policyNode, (Map.Entry) obj, depth); + } else if (obj instanceof Collection && !(obj instanceof Enumeration)) { + if (obj instanceof List) { + trackList(event, policyNode, (List) obj, depth); + } else { + trackIterator(event, policyNode, ((Collection) obj).iterator(), depth); + } + } else if ("java.util.Optional".equals(obj.getClass().getName())) { + trackOptional(event, policyNode, obj, depth); + } else { + if (isSourceNode) { + int len = TaintRangesBuilder.getLength(obj); + if (hash == 0 || len == 0) { + return; + } + + SourceNode sourceNode = (SourceNode) policyNode; + TaintRanges tr = new TaintRanges(new TaintRange(0, len)); + if (sourceNode.hasTags()) { + String[] tags = sourceNode.getTags(); + for (String tag : tags) { + tr.add(new TaintRange(tag, 0, len)); + } + } + event.targetRanges.add(new MethodEvent.MethodEventTargetRange(hash, tr)); + + EngineManager.TAINT_HASH_CODES.add(hash); + event.addTargetHash(hash); + EngineManager.TAINT_RANGES_POOL.add(hash, tr); + } else { + if (!(obj instanceof String)) { + Set modelValues = TaintPoolUtils.parseCustomModel(obj); + for (Object modelValue : modelValues) { + trackObject(event, policyNode, modelValue, depth + 1); + } + } + + hash = System.identityHashCode(obj); + if (EngineManager.TAINT_HASH_CODES.contains(hash)) { + event.addSourceHash(hash); + } + } + } + } + + private static void trackArray(MethodEvent event, PolicyNode policyNode, Object arr, int depth) { + int length = Array.getLength(arr); + for (int i = 0; i < length; i++) { + trackObject(event, policyNode, Array.get(arr, i), depth + 1); + } + } + + private static void trackIterator(MethodEvent event, PolicyNode policyNode, Iterator it, int depth) { + while (it.hasNext()) { + trackObject(event, policyNode, it.next(), depth + 1); + } + } + + private static void trackMap(MethodEvent event, PolicyNode policyNode, Map map, int depth) { + for (Object key : map.keySet()) { + trackObject(event, policyNode, key, depth + 1); + trackObject(event, policyNode, map.get(key), depth + 1); + } + } + + private static void trackMapEntry(MethodEvent event, PolicyNode policyNode, Map.Entry entry, int depth) { + trackObject(event, policyNode, entry.getKey(), depth + 1); + trackObject(event, policyNode, entry.getValue(), depth + 1); + } + + private static void trackList(MethodEvent event, PolicyNode policyNode, List list, int depth) { + for (Object obj : list) { + trackObject(event, policyNode, obj, depth + 1); + } + } + + private static void trackOptional(MethodEvent event, PolicyNode policyNode, Object obj, int depth) { + try { + Object v = ((Optional) obj).orElse(null); + trackObject(event, policyNode, v, depth + 1); + } catch (Throwable ignore) { + } + } } diff --git a/dongtai-log/src/main/java/io/dongtai/log/ErrorCode.java b/dongtai-log/src/main/java/io/dongtai/log/ErrorCode.java index 86add87f3..1d6b31fcd 100644 --- a/dongtai-log/src/main/java/io/dongtai/log/ErrorCode.java +++ b/dongtai-log/src/main/java/io/dongtai/log/ErrorCode.java @@ -78,6 +78,7 @@ public enum ErrorCode { SPY_COLLECT_METHOD_FAILED(20303, "hookpoint collect method failed"), SPY_TRACE_FEIGN_INVOKE_FAILED(20304, "hookpoint trace feign invoke failed"), SPY_METHOD_POOL_OVER_CAPACITY(20305, "current request method pool size over capacity: {}"), + SPY_TRACE_DUBBO_INVOKE_FAILED(20306, "hookpoint trace dubbo invoke failed"), API_COLLECTOR_GET_API_THREAD_EXECUTE_FAILED(20311, "get api thread execute failed"), GRAPH_BUILD_AND_REPORT_FAILED(20321, "build and report request graph failed"), TAINT_COMMAND_GET_PARAMETERS_FAILED(20351, "taint command get {} parameters failed"), diff --git a/dongtai-spy/src/main/java/java/lang/dongtai/NopSpy.java b/dongtai-spy/src/main/java/java/lang/dongtai/NopSpy.java index 85a15ad52..275b82299 100644 --- a/dongtai-spy/src/main/java/java/lang/dongtai/NopSpy.java +++ b/dongtai-spy/src/main/java/java/lang/dongtai/NopSpy.java @@ -1,7 +1,6 @@ package java.lang.dongtai; -import java.util.Collection; -import java.util.Enumeration; +import java.util.*; public class NopSpy implements SpyDispatcher { @Override @@ -218,4 +217,11 @@ public boolean traceFeignInvoke(Object instance, Object[] parameters, String className, String methodName, String signature) { return false; } + + @Override + public boolean traceDubboInvoke(Object instance, String url, Object invocation, Object[] arguments, + Map headers, String className, String methodName, + String signature) { + return false; + } } diff --git a/dongtai-spy/src/main/java/java/lang/dongtai/SpyDispatcher.java b/dongtai-spy/src/main/java/java/lang/dongtai/SpyDispatcher.java index b09c565bc..07a281a9d 100644 --- a/dongtai-spy/src/main/java/java/lang/dongtai/SpyDispatcher.java +++ b/dongtai-spy/src/main/java/java/lang/dongtai/SpyDispatcher.java @@ -1,7 +1,6 @@ package java.lang.dongtai; -import java.util.Collection; -import java.util.Enumeration; +import java.util.*; public interface SpyDispatcher { @@ -146,4 +145,8 @@ public boolean collectMethod(Object instance, Object[] parameters, Object retObj boolean traceFeignInvoke(Object instance, Object[] parameters, String className, String methodName, String signature); + + boolean traceDubboInvoke(Object instance, String url, Object invocation, Object[] arguments, + Map headers, String className, String methodName, + String signature); } From 82198981137f3404facb5ff2750c72957321bf8b Mon Sep 17 00:00:00 2001 From: lostsnow Date: Fri, 3 Mar 2023 11:12:06 +0800 Subject: [PATCH 3/7] add dubbo provider track --- .../io/dongtai/iast/common/scope/Scope.java | 3 + .../iast/common/scope/ScopeAggregator.java | 15 ++ .../iast/common/scope/ScopeTracker.java | 8 +- .../io/dongtai/iast/core/EngineManager.java | 8 ++ .../core/bytecode/enhance/asm/AsmMethods.java | 44 ++++++ .../plugin/framework/dubbo/DispatchDubbo.java | 6 + ...bboExchangeHandleRequestAdviceAdapter.java | 128 +++++++++++++++++ .../LegacyDubboExchangeHandlerAdapter.java | 29 ++++ .../dubbo/LegacyDubboProxyHandlerAdapter.java | 29 ++++ ...yDubboProxyHandlerInvokeAdviceAdapter.java | 67 +++++++++ .../dubbo/LegacyDubboSyncHandlerAdapter.java | 2 +- ...cyDubboSyncHandlerInvokeAdviceAdapter.java | 2 +- .../handler/hookpoint/SpyDispatcherImpl.java | 95 ++++++++++++- .../hookpoint/controller/impl/DubboImpl.java | 130 ++++++++++++++++++ .../hookpoint/graphy/GraphBuilder.java | 2 +- .../handler/hookpoint/models/MethodEvent.java | 4 + .../models/policy/PolicyManager.java | 4 +- .../models/policy/PropagatorNode.java | 1 + .../hookpoint/models/policy/SinkNode.java | 1 + .../hookpoint/models/policy/SourceNode.java | 1 + .../hookpoint/service/trace/DubboService.java | 2 - .../vulscan/normal/AbstractNormalVulScan.java | 7 +- .../main/java/io/dongtai/log/ErrorCode.java | 4 +- .../main/java/java/lang/dongtai/NopSpy.java | 29 +++- .../java/java/lang/dongtai/SpyDispatcher.java | 15 ++ 25 files changed, 622 insertions(+), 14 deletions(-) create mode 100644 dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboExchangeHandleRequestAdviceAdapter.java create mode 100644 dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboExchangeHandlerAdapter.java create mode 100644 dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboProxyHandlerAdapter.java create mode 100644 dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboProxyHandlerInvokeAdviceAdapter.java create mode 100644 dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/controller/impl/DubboImpl.java diff --git a/dongtai-common/src/main/java/io/dongtai/iast/common/scope/Scope.java b/dongtai-common/src/main/java/io/dongtai/iast/common/scope/Scope.java index 84cc20a9d..d250092fa 100644 --- a/dongtai-common/src/main/java/io/dongtai/iast/common/scope/Scope.java +++ b/dongtai-common/src/main/java/io/dongtai/iast/common/scope/Scope.java @@ -5,6 +5,9 @@ public enum Scope { HTTP_ENTRY(2), SERVLET_INPUT_STREAM_READ(3), SERVLET_OUTPUT_WRITE(4), + DUBBO_REQUEST(5), + DUBBO_ENTRY(6), + DUBBO_SOURCE(7), ; private final int id; diff --git a/dongtai-common/src/main/java/io/dongtai/iast/common/scope/ScopeAggregator.java b/dongtai-common/src/main/java/io/dongtai/iast/common/scope/ScopeAggregator.java index 34fecc593..9876d8929 100644 --- a/dongtai-common/src/main/java/io/dongtai/iast/common/scope/ScopeAggregator.java +++ b/dongtai-common/src/main/java/io/dongtai/iast/common/scope/ScopeAggregator.java @@ -3,6 +3,9 @@ public class ScopeAggregator { private final GeneralScope httpRequestScope = new GeneralScope(); private final GeneralScope httpEntryScope = new GeneralScope(); + private final GeneralScope dubboRequestScope = new GeneralScope(); + private final GeneralScope dubboEntryScope = new GeneralScope(); + private final GeneralScope dubboSourceScope = new GeneralScope(); private final GeneralScope servletInputStreamReadScope = new GeneralScope(); private final GeneralScope servletOutputStreamWriteScope = new GeneralScope(); private final PolicyScope policyScope = new PolicyScope(); @@ -15,6 +18,18 @@ public GeneralScope getHttpEntryScope() { return httpEntryScope; } + public GeneralScope getDubboRequestScope() { + return dubboRequestScope; + } + + public GeneralScope getDubboEntryScope() { + return dubboEntryScope; + } + + public GeneralScope getDubboSourceScope() { + return dubboSourceScope; + } + public GeneralScope getServletInputStreamReadScope() { return servletInputStreamReadScope; } diff --git a/dongtai-common/src/main/java/io/dongtai/iast/common/scope/ScopeTracker.java b/dongtai-common/src/main/java/io/dongtai/iast/common/scope/ScopeTracker.java index 3044ea2d9..7af9b2a3f 100644 --- a/dongtai-common/src/main/java/io/dongtai/iast/common/scope/ScopeTracker.java +++ b/dongtai-common/src/main/java/io/dongtai/iast/common/scope/ScopeTracker.java @@ -16,13 +16,19 @@ public GeneralScope getScope(Scope scope) { return this.get().getServletInputStreamReadScope(); case SERVLET_OUTPUT_WRITE: return this.get().getServletOutputStreamWriteScope(); + case DUBBO_REQUEST: + return this.get().getDubboRequestScope(); + case DUBBO_ENTRY: + return this.get().getDubboEntryScope(); + case DUBBO_SOURCE: + return this.get().getDubboSourceScope(); default: return null; } } public boolean inEnterEntry() { - return this.get().getHttpEntryScope().in(); + return this.get().getHttpEntryScope().in() || this.get().getDubboRequestScope().in(); } public PolicyScope getPolicyScope() { diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/EngineManager.java b/dongtai-core/src/main/java/io/dongtai/iast/core/EngineManager.java index 53aa0311f..150670aa4 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/EngineManager.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/EngineManager.java @@ -140,4 +140,12 @@ public static void enterHttpEntry(Map requestMeta) { TAINT_RANGES_POOL.set(new HashMap()); ScopeManager.SCOPE_TRACKER.getScope(Scope.HTTP_ENTRY).enter(); } + + public static void enterDubboEntry(Map requestMeta) { + REQUEST_CONTEXT.set(requestMeta); + TRACK_MAP.set(new HashMap(1024)); + TAINT_HASH_CODES.set(new HashSet()); + TAINT_RANGES_POOL.set(new HashMap()); + ScopeManager.SCOPE_TRACKER.getScope(Scope.DUBBO_ENTRY).enter(); + } } diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/asm/AsmMethods.java b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/asm/AsmMethods.java index 29573afbf..67dfa1ed7 100755 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/asm/AsmMethods.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/asm/AsmMethods.java @@ -4,6 +4,7 @@ import java.lang.dongtai.SpyDispatcher; import java.lang.dongtai.SpyDispatcherHandler; +import java.net.InetSocketAddress; import java.util.*; /** @@ -131,6 +132,49 @@ static Method getAsmMethod(final Class clazz, int.class ); + Method SPY$enterDubbo = InnerHelper.getAsmMethod( + SpyDispatcher.class, + "enterDubbo" + ); + Method SPY$leaveDubbo = InnerHelper.getAsmMethod( + SpyDispatcher.class, + "leaveDubbo", + Object.class, + Object.class, + Object.class, + byte.class + ); + Method SPY$isFirstLevelDubbo = InnerHelper.getAsmMethod( + SpyDispatcher.class, + "isFirstLevelDubbo" + ); + Method SPY$collectDubboRequest = InnerHelper.getAsmMethod( + SpyDispatcher.class, + "collectDubboRequest", + Object.class, + Object.class, + Object.class, + String.class, + InetSocketAddress.class, + boolean.class, + boolean.class, + boolean.class, + boolean.class + ); + + Method SPY$collectDubboRequestSource = InnerHelper.getAsmMethod( + SpyDispatcher.class, + "collectDubboRequestSource", + Object.class, + Object.class, + String.class, + Object[].class, + Map.class, + String.class, + String.class, + String.class + ); + Method SPY$enterSource = InnerHelper.getAsmMethod( SpyDispatcher.class, "enterSource" diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DispatchDubbo.java b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DispatchDubbo.java index b20445ee0..5c626e07c 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DispatchDubbo.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DispatchDubbo.java @@ -7,6 +7,8 @@ public class DispatchDubbo implements DispatchPlugin { public static final String LEGACY_DUBBO_SYNC_HANDLER = " com.alibaba.dubbo.rpc.listener.ListenerInvokerWrapper".substring(1); + public static final String LEGACY_DUBBO_EXCHANGE_HANDLER = " com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeHandler".substring(1); + public static final String LEGACY_DUBBO_PROXY_HANDLER = " com.alibaba.dubbo.rpc.proxy.AbstractProxyInvoker".substring(1); @Override public ClassVisitor dispatch(ClassVisitor classVisitor, ClassContext context, Policy policy) { @@ -14,6 +16,10 @@ public ClassVisitor dispatch(ClassVisitor classVisitor, ClassContext context, Po if (LEGACY_DUBBO_SYNC_HANDLER.equals(className)) { classVisitor = new LegacyDubboSyncHandlerAdapter(classVisitor, context); + } else if (LEGACY_DUBBO_EXCHANGE_HANDLER.equals(className)) { + classVisitor = new LegacyDubboExchangeHandlerAdapter(classVisitor, context); + } else if (LEGACY_DUBBO_PROXY_HANDLER.equals(className)) { + classVisitor = new LegacyDubboProxyHandlerAdapter(classVisitor, context); } return classVisitor; diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboExchangeHandleRequestAdviceAdapter.java b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboExchangeHandleRequestAdviceAdapter.java new file mode 100644 index 000000000..12fefb307 --- /dev/null +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboExchangeHandleRequestAdviceAdapter.java @@ -0,0 +1,128 @@ +package io.dongtai.iast.core.bytecode.enhance.plugin.framework.dubbo; + +import io.dongtai.iast.core.bytecode.enhance.ClassContext; +import io.dongtai.iast.core.bytecode.enhance.plugin.AbstractAdviceAdapter; +import org.objectweb.asm.*; +import org.objectweb.asm.commons.Method; + +public class LegacyDubboExchangeHandleRequestAdviceAdapter extends AbstractAdviceAdapter { + private static final Method GET_URL_METHOD = Method.getMethod(" com.alibaba.dubbo.common.URL getUrl()".substring(1)); + private static final Method URL_TO_STRING_METHOD = Method.getMethod("java.lang.String toString()"); + private static final Method GET_REMOTE_ADDRESS_METHOD = Method.getMethod("java.net.InetSocketAddress getRemoteAddress()"); + private static final Method IS_TWO_WAY_METHOD = Method.getMethod("boolean isTwoWay()"); + private static final Method IS_EVENT_METHOD = Method.getMethod("boolean isEvent()"); + private static final Method IS_BROKEN_METHOD = Method.getMethod("boolean isBroken()"); + private static final Method IS_HEARTBEAT_METHOD = Method.getMethod("boolean isHeartbeat()"); + private static final Method GET_RESULT_METHOD = Method.getMethod("java.lang.Object getResult()"); + private static final Method GET_STATUS_METHOD = Method.getMethod("byte getStatus()"); + + private final Type endpointType; + private final Type urlType; + private final Type channelType; + private final Type requestType; + private final Type responseType; + + protected LegacyDubboExchangeHandleRequestAdviceAdapter(MethodVisitor mv, int access, String name, String desc, String signature, ClassContext context) { + super(mv, access, name, desc, context, "dubbo", signature); + this.endpointType = Type.getObjectType(" com/alibaba/dubbo/remoting/Endpoint".substring(1)); + this.urlType = Type.getObjectType(" com/alibaba/dubbo/common/URL".substring(1)); + this.channelType = Type.getObjectType(" com/alibaba/dubbo/remoting/Channel".substring(1)); + this.requestType = Type.getObjectType(" com/alibaba/dubbo/remoting/exchange/Request".substring(1)); + this.responseType = Type.getObjectType(" com/alibaba/dubbo/remoting/exchange/Response".substring(1)); + } + + @Override + protected void before() { + mark(tryLabel); + Label elseLabel = new Label(); + + enterDubbo(); + isFirstLevelDubbo(); + mv.visitJumpInsn(EQ, elseLabel); + + collectDubboRequest(); + + mark(elseLabel); + } + + @Override + protected void after(int opcode) { + // if (opcode != ATHROW) { + // Label elseLabel = new Label(); + // isFirstLevelDubbo(); + // mv.visitJumpInsn(EQ, elseLabel); + // collectDubboResponse(opcode); + // mark(elseLabel); + // } + + leaveDubbo(opcode); + } + + private void enterDubbo() { + invokeStatic(ASM_TYPE_SPY_HANDLER, SPY_HANDLER$getDispatcher); + invokeInterface(ASM_TYPE_SPY_DISPATCHER, SPY$enterDubbo); + } + + private void leaveDubbo(int opcode) { + int retLocal = newLocal(ASM_TYPE_OBJECT); + if (!isThrow(opcode)) { + loadReturn(opcode); + } else { + pushNull(); + } + storeLocal(retLocal); + invokeStatic(ASM_TYPE_SPY_HANDLER, SPY_HANDLER$getDispatcher); + loadArg(1); + loadLocal(retLocal); + if (!isThrow(opcode)) { + loadLocal(retLocal); + invokeVirtual(this.responseType, GET_RESULT_METHOD); + loadLocal(retLocal); + invokeVirtual(this.responseType, GET_STATUS_METHOD); + } else { + pushNull(); + byte b = 0; + push(b); + } + invokeInterface(ASM_TYPE_SPY_DISPATCHER, SPY$leaveDubbo); + } + + private void isFirstLevelDubbo() { + invokeStatic(ASM_TYPE_SPY_HANDLER, SPY_HANDLER$getDispatcher); + invokeInterface(ASM_TYPE_SPY_DISPATCHER, SPY$isFirstLevelDubbo); + } + + private void collectDubboRequest() { + Label tryL = new Label(); + Label catchL = new Label(); + Label exHandlerL = new Label(); + visitTryCatchBlock(tryL, catchL, exHandlerL, ASM_TYPE_THROWABLE.getInternalName()); + visitLabel(tryL); + + invokeStatic(ASM_TYPE_SPY_HANDLER, SPY_HANDLER$getDispatcher); + loadThis(); + loadArg(0); + loadArg(1); + loadArg(0); + invokeInterface(this.endpointType, GET_URL_METHOD); + invokeVirtual(this.urlType, URL_TO_STRING_METHOD); + loadArg(0); + invokeInterface(this.channelType, GET_REMOTE_ADDRESS_METHOD); + loadArg(1); + invokeVirtual(this.requestType, IS_TWO_WAY_METHOD); + loadArg(1); + invokeVirtual(this.requestType, IS_EVENT_METHOD); + loadArg(1); + invokeVirtual(this.requestType, IS_BROKEN_METHOD); + loadArg(1); + invokeVirtual(this.requestType, IS_HEARTBEAT_METHOD); + invokeInterface(ASM_TYPE_SPY_DISPATCHER, SPY$collectDubboRequest); + + visitLabel(catchL); + Label endL = new Label(); + visitJumpInsn(GOTO, endL); + visitLabel(exHandlerL); + visitVarInsn(ASTORE, this.nextLocal); + visitLabel(endL); + } +} diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboExchangeHandlerAdapter.java b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboExchangeHandlerAdapter.java new file mode 100644 index 000000000..dedba4cdc --- /dev/null +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboExchangeHandlerAdapter.java @@ -0,0 +1,29 @@ +package io.dongtai.iast.core.bytecode.enhance.plugin.framework.dubbo; + +import io.dongtai.iast.core.bytecode.enhance.ClassContext; +import io.dongtai.iast.core.bytecode.enhance.plugin.AbstractClassVisitor; +import io.dongtai.iast.core.utils.AsmUtils; +import io.dongtai.log.DongTaiLog; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; + +public class LegacyDubboExchangeHandlerAdapter extends AbstractClassVisitor { + public static final String LEGACY_DUBBO_EXCHANGE_HANDLE_REQUEST = " com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.handleRequest(com.alibaba.dubbo.remoting.exchange.ExchangeChannel,com.alibaba.dubbo.remoting.exchange.Request)".substring(1); + + public LegacyDubboExchangeHandlerAdapter(ClassVisitor classVisitor, ClassContext context) { + super(classVisitor, context); + } + + @Override + public MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) { + MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); + String signCode = AsmUtils.buildSignature(context.getClassName(), name, desc); + + if (LEGACY_DUBBO_EXCHANGE_HANDLE_REQUEST.equals(signCode)) { + DongTaiLog.debug("Adding dubbo provider tracking by {}", signCode); + mv = new LegacyDubboExchangeHandleRequestAdviceAdapter(mv, access, name, desc, signCode, this.context); + setTransformed(); + } + return mv; + } +} diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboProxyHandlerAdapter.java b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboProxyHandlerAdapter.java new file mode 100644 index 000000000..b0079c7c7 --- /dev/null +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboProxyHandlerAdapter.java @@ -0,0 +1,29 @@ +package io.dongtai.iast.core.bytecode.enhance.plugin.framework.dubbo; + +import io.dongtai.iast.core.bytecode.enhance.ClassContext; +import io.dongtai.iast.core.bytecode.enhance.plugin.AbstractClassVisitor; +import io.dongtai.iast.core.utils.AsmUtils; +import io.dongtai.log.DongTaiLog; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; + +public class LegacyDubboProxyHandlerAdapter extends AbstractClassVisitor { + public static final String LEGACY_DUBBO_PROXY_HANDLER_INVOKE = " com.alibaba.dubbo.rpc.proxy.AbstractProxyInvoker.invoke(com.alibaba.dubbo.rpc.Invocation)".substring(1); + + public LegacyDubboProxyHandlerAdapter(ClassVisitor classVisitor, ClassContext context) { + super(classVisitor, context); + } + + @Override + public MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) { + MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); + String signCode = AsmUtils.buildSignature(context.getClassName(), name, desc); + + if (LEGACY_DUBBO_PROXY_HANDLER_INVOKE.equals(signCode)) { + DongTaiLog.debug("Adding dubbo provider source tracking by {}", signCode); + mv = new LegacyDubboProxyHandlerInvokeAdviceAdapter(mv, access, name, desc, signCode, this.context); + setTransformed(); + } + return mv; + } +} diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboProxyHandlerInvokeAdviceAdapter.java b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboProxyHandlerInvokeAdviceAdapter.java new file mode 100644 index 000000000..ab1dd8fc1 --- /dev/null +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboProxyHandlerInvokeAdviceAdapter.java @@ -0,0 +1,67 @@ +package io.dongtai.iast.core.bytecode.enhance.plugin.framework.dubbo; + +import io.dongtai.iast.common.scope.Scope; +import io.dongtai.iast.core.bytecode.enhance.ClassContext; +import io.dongtai.iast.core.bytecode.enhance.plugin.AbstractAdviceAdapter; +import org.objectweb.asm.*; +import org.objectweb.asm.commons.Method; + +public class LegacyDubboProxyHandlerInvokeAdviceAdapter extends AbstractAdviceAdapter { + private static final Method GET_ARGUMENTS_METHOD = Method.getMethod("java.lang.Object[] getArguments()"); + private static final Method GET_GETATTACHMENTS_METHOD = Method.getMethod("java.util.Map getAttachments()"); + private static final Method GET_METHOD_NAME_METHOD = Method.getMethod("java.lang.String getMethodName()"); + + private final Type invocationType; + + protected LegacyDubboProxyHandlerInvokeAdviceAdapter(MethodVisitor mv, int access, String name, String desc, String signature, ClassContext context) { + super(mv, access, name, desc, context, "dubbo", signature); + this.invocationType = Type.getObjectType(" com/alibaba/dubbo/rpc/Invocation".substring(1)); + } + + @Override + protected void before() { + mark(tryLabel); + + enterScope(Scope.DUBBO_SOURCE); + + Label elseLabel = new Label(); + isFirstLevelScope(Scope.DUBBO_SOURCE); + mv.visitJumpInsn(EQ, elseLabel); + collectDubboRequestSource(); + mark(elseLabel); + } + + @Override + protected void after(int opcode) { + leaveScope(Scope.DUBBO_SOURCE); + } + + private void collectDubboRequestSource() { + Label tryL = new Label(); + Label catchL = new Label(); + Label exHandlerL = new Label(); + visitTryCatchBlock(tryL, catchL, exHandlerL, ASM_TYPE_THROWABLE.getInternalName()); + visitLabel(tryL); + + invokeStatic(ASM_TYPE_SPY_HANDLER, SPY_HANDLER$getDispatcher); + loadThis(); + loadArg(0); + loadArg(0); + invokeInterface(this.invocationType, GET_METHOD_NAME_METHOD); + loadArg(0); + invokeInterface(this.invocationType, GET_ARGUMENTS_METHOD); + loadArg(0); + invokeInterface(this.invocationType, GET_GETATTACHMENTS_METHOD); + push(this.classContext.getClassName()); + push(this.name); + push(this.signature); + invokeInterface(ASM_TYPE_SPY_DISPATCHER, SPY$collectDubboRequestSource); + + visitLabel(catchL); + Label endL = new Label(); + visitJumpInsn(GOTO, endL); + visitLabel(exHandlerL); + visitVarInsn(ASTORE, this.nextLocal); + visitLabel(endL); + } +} diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboSyncHandlerAdapter.java b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboSyncHandlerAdapter.java index 60915f050..698d685bf 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboSyncHandlerAdapter.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboSyncHandlerAdapter.java @@ -20,7 +20,7 @@ public MethodVisitor visitMethod(final int access, final String name, final Stri String signCode = AsmUtils.buildSignature(context.getClassName(), name, desc); if (LEGACY_DUBBO_SYNC_HANDLER_INVOKE.equals(signCode)) { - DongTaiLog.debug("Adding dubbo tracking by {}", signCode); + DongTaiLog.debug("Adding dubbo consumer tracking by {}", signCode); mv = new LegacyDubboSyncHandlerInvokeAdviceAdapter(mv, access, name, desc, signCode, this.context); setTransformed(); } diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboSyncHandlerInvokeAdviceAdapter.java b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboSyncHandlerInvokeAdviceAdapter.java index 161d09c06..a92c18bb8 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboSyncHandlerInvokeAdviceAdapter.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboSyncHandlerInvokeAdviceAdapter.java @@ -93,7 +93,7 @@ private void isFirstScope() { private void traceMethod() { invokeStatic(ASM_TYPE_SPY_HANDLER, SPY_HANDLER$getDispatcher); - loadThisOrPushNullIfIsStatic(); + loadThis(); dup(); invokeVirtual(this.handlerType, GET_URL_METHOD); invokeVirtual(this.urlType, URL_TO_STRING_METHOD); diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/SpyDispatcherImpl.java b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/SpyDispatcherImpl.java index adec8ce7d..c65ca60a6 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/SpyDispatcherImpl.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/SpyDispatcherImpl.java @@ -18,6 +18,7 @@ import io.dongtai.log.ErrorCode; import java.lang.dongtai.SpyDispatcher; +import java.net.InetSocketAddress; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; @@ -149,6 +150,7 @@ public boolean isFirstLevelHttp() { } } + @Override public void collectHttpRequest(Object obj, Object req, Object resp, StringBuffer requestURL, String requestURI, String queryString, String method, String protocol, String scheme, String serverName, String contextPath, String remoteAddr, @@ -266,6 +268,97 @@ public void onPrintWriterWrite(String desc, Object writer, int b, String s, char } } + @Override + public void enterDubbo() { + if (!EngineManager.isEngineRunning()) { + return; + } + try { + ScopeManager.SCOPE_TRACKER.getScope(Scope.DUBBO_REQUEST).enter(); + } catch (Throwable ignore) { + } + } + + @Override + public void leaveDubbo(Object request, Object response, Object result, byte status) { + if (!EngineManager.isEngineRunning()) { + EngineManager.cleanThreadState(); + return; + } + try { + if (ScopeManager.SCOPE_TRACKER.getScope(Scope.DUBBO_REQUEST).isFirst() + && ScopeManager.SCOPE_TRACKER.getScope(Scope.DUBBO_ENTRY).in()) { + DubboImpl.collectDubboResponse(result, status); + } + + ScopeManager.SCOPE_TRACKER.getScope(Scope.DUBBO_REQUEST).leave(); + if (!ScopeManager.SCOPE_TRACKER.getScope(Scope.DUBBO_REQUEST).in() + && ScopeManager.SCOPE_TRACKER.getScope(Scope.DUBBO_ENTRY).in()) { + EngineManager.maintainRequestCount(); + GraphBuilder.buildAndReport(request, response); + EngineManager.cleanThreadState(); + } + } catch (Throwable e) { + DongTaiLog.error(ErrorCode.SPY_LEAVE_DUBBO_FAILED, e); + EngineManager.cleanThreadState(); + } + } + + @Override + public boolean isFirstLevelDubbo() { + if (!EngineManager.isEngineRunning()) { + return false; + } + try { + return ScopeManager.SCOPE_TRACKER.getScope(Scope.DUBBO_REQUEST).isFirst(); + } catch (Throwable ignore) { + return false; + } + } + + @Override + public void collectDubboRequest(Object handler, Object channel, Object request, + String url, InetSocketAddress remoteAddress, + boolean isTwoWay, boolean isEvent, boolean isBroken, boolean isHeartbeat) { + try { + ScopeManager.SCOPE_TRACKER.getPolicyScope().enterAgent(); + + if (!EngineManager.isEngineRunning()) { + return; + } + + if (isEvent || isBroken || isHeartbeat || !isTwoWay) { + return; + } + + DubboImpl.solveDubboRequest(handler, channel, request, url, remoteAddress.getAddress().getHostAddress()); + } catch (Throwable e) { + DongTaiLog.warn(ErrorCode.SPY_COLLECT_DUBBO_FAILED, "request", e); + } finally { + ScopeManager.SCOPE_TRACKER.getPolicyScope().leaveAgent(); + } + } + + @Override + public void collectDubboRequestSource(Object handler, Object invocation, String methodName, + Object[] arguments, Map headers, + String hookClass, String hookMethod, String hookSign) { + try { + ScopeManager.SCOPE_TRACKER.getPolicyScope().enterAgent(); + + if (!EngineManager.isEngineRunning()) { + return; + } + + DubboImpl.collectDubboRequestSource(handler, invocation, methodName, arguments, headers, + hookClass, hookMethod, hookSign, INVOKE_ID_SEQUENCER); + } catch (Throwable e) { + DongTaiLog.warn(ErrorCode.SPY_COLLECT_DUBBO_FAILED, "request source", e); + } finally { + ScopeManager.SCOPE_TRACKER.getPolicyScope().leaveAgent(); + } + } + /** * mark for enter Source Entry Point * @@ -551,7 +644,7 @@ public boolean traceDubboInvoke(Object instance, String url, Object invocation, DubboService.solveSyncInvoke(event, invocation, url, headers, INVOKE_ID_SEQUENCER); } catch (Throwable e) { - DongTaiLog.error(ErrorCode.SPY_TRACE_DUBBO_INVOKE_FAILED, e); + DongTaiLog.error(ErrorCode.SPY_TRACE_DUBBO_CONSUMER_INVOKE_FAILED, e); } finally { ScopeManager.SCOPE_TRACKER.getPolicyScope().leaveAgent(); } diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/controller/impl/DubboImpl.java b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/controller/impl/DubboImpl.java new file mode 100644 index 000000000..e54cc8e09 --- /dev/null +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/controller/impl/DubboImpl.java @@ -0,0 +1,130 @@ +package io.dongtai.iast.core.handler.hookpoint.controller.impl; + +import io.dongtai.iast.common.config.*; +import io.dongtai.iast.core.EngineManager; +import io.dongtai.iast.core.handler.context.ContextManager; +import io.dongtai.iast.core.handler.hookpoint.models.MethodEvent; +import io.dongtai.iast.core.handler.hookpoint.models.policy.SourceNode; +import io.dongtai.iast.core.handler.hookpoint.models.policy.TaintPosition; +import io.dongtai.iast.core.utils.StackUtils; +import io.dongtai.iast.core.utils.TaintPoolUtils; +import io.dongtai.log.DongTaiLog; +import org.json.JSONArray; + +import java.io.ByteArrayOutputStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; + +public class DubboImpl { + public static void solveDubboRequest(Object handler, Object channel, Object request, String url, String remoteAddress) { + try { + URI u = new URI(url); + Map requestMeta = new HashMap() {{ + put("requestURL", u.getScheme() + "://" + u.getAuthority() + u.getPath()); + put("requestURI", u.getPath()); + put("queryString", ""); + put("method", "DUBOO"); + put("protocol", "DUBBO"); + put("scheme", u.getScheme()); + put("contextPath", ""); + put("remoteAddr", "0:0:0:0:0:0:0:1".equals(remoteAddress) ? "127.0.0.1" : remoteAddress); + put("secure", false); + put("serverPort", u.getPort()); + }}; + + EngineManager.enterDubboEntry(requestMeta); + DongTaiLog.debug("Dubbo: {}", request.toString()); + } catch (URISyntaxException ignore) { + } + } + + + + public static void collectDubboRequestSource(Object handler, Object invocation, String methodName, + Object[] arguments, Map headers, + String hookClass, String hookMethod, String hookSign, + AtomicInteger invokeIdSequencer) { + if (arguments == null || arguments.length == 0) { + return; + } + Map requestMeta = EngineManager.REQUEST_CONTEXT.get(); + if (requestMeta == null) { + return; + } + + String url = (String) requestMeta.get("requestURL") + "/" + methodName; + String uri = (String) requestMeta.get("requestURI") + "/" + methodName; + requestMeta.put("requestURL", url); + requestMeta.put("requestURI", uri); + + MethodEvent event = new MethodEvent(hookClass, hookClass, hookMethod, + hookSign, null, arguments, null); + + HashSet src = new HashSet(); + HashSet tgt = new HashSet(); + src.add(new TaintPosition("O")); + tgt.add(new TaintPosition("P1")); + + SourceNode sourceNode = new SourceNode(src, tgt, null); + if (arguments != null && arguments.length > 0) { + TaintPoolUtils.trackObject(event, sourceNode, arguments, 0); + } + if (headers != null && !headers.isEmpty()) { + String traceIdKey = ContextManager.getHeaderKey(); + if (headers.containsKey(traceIdKey)) { + ContextManager.parseTraceId(headers.get(traceIdKey)); + } else { + String newTraceId = ContextManager.currentTraceId(); + headers.put(traceIdKey, newTraceId); + } + } + + if (event.getTargetHashes().isEmpty()) { + return; + } + + event.addParameterValue(0, arguments, true); + event.setObjectValue(handler, false); + event.setTaintPositions(sourceNode.getSources(), sourceNode.getTargets()); + + requestMeta.put("headers", headers); + JSONArray arr = new JSONArray(); + for (Object arg : arguments) { + arr.put(event.obj2String(arg)); + } + requestMeta.put("body", arr.toString()); + EngineManager.REQUEST_CONTEXT.set(requestMeta); + + int invokeId = invokeIdSequencer.getAndIncrement(); + event.setInvokeId(invokeId); + + event.source = true; + event.setCallStacks(StackUtils.createCallStack(4)); + + EngineManager.TRACK_MAP.addTrackMethod(invokeId, event); + } + + public static void collectDubboResponse(Object result, byte status) { + if (result == null) { + return; + } + try { + boolean getBody = ((Config) ConfigBuilder.getInstance().getConfig(ConfigKey.REPORT_RESPONSE_BODY)).get(); + if (!getBody) { + return; + } + } catch (Throwable ignore) { + return; + } + + try { + EngineManager.REQUEST_CONTEXT.get().put("responseStatus", + (String) EngineManager.REQUEST_CONTEXT.get().get("protocol") + " " + status); + ByteArrayOutputStream buff = EngineManager.BODY_BUFFER.getResponse(); + buff.write(result.toString().getBytes()); + } catch (Throwable ignore) { + } + } +} diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/graphy/GraphBuilder.java b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/graphy/GraphBuilder.java index d72a17494..d4c09ede0 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/graphy/GraphBuilder.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/graphy/GraphBuilder.java @@ -71,7 +71,7 @@ public static String convertToReport(List nodeList, Object request, O detail.put(ReportKey.PROTOCOL, requestMeta.getOrDefault("protocol", "unknown")); detail.put(ReportKey.SCHEME, requestMeta.getOrDefault("scheme", "")); detail.put(ReportKey.METHOD, requestMeta.getOrDefault("method", "")); - detail.put(ReportKey.SECURE, requestMeta.getOrDefault("secure", "")); + detail.put(ReportKey.SECURE, requestMeta.getOrDefault("secure", false)); String requestURL = requestMeta.getOrDefault("requestURL", "").toString(); if (StringUtils.isEmpty(requestURL)) { return null; diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/models/MethodEvent.java b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/models/MethodEvent.java index cb5b5a9fe..de141a7f2 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/models/MethodEvent.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/models/MethodEvent.java @@ -103,6 +103,10 @@ public Parameter(String index, String value) { this.value = value; } + public String getValue() { + return this.value; + } + public JSONObject toJson() { JSONObject json = new JSONObject(); json.put("index", this.index); diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/models/policy/PolicyManager.java b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/models/policy/PolicyManager.java index 3624c1329..23dd0e723 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/models/policy/PolicyManager.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/models/policy/PolicyManager.java @@ -30,7 +30,9 @@ public class PolicyManager { " javax.servlet.http.Cookie".substring(1), " org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker".substring(1), DispatchFeign.FEIGN_SYNC_HANDLER, - DispatchDubbo.LEGACY_DUBBO_SYNC_HANDLER + DispatchDubbo.LEGACY_DUBBO_SYNC_HANDLER, + DispatchDubbo.LEGACY_DUBBO_EXCHANGE_HANDLER, + DispatchDubbo.LEGACY_DUBBO_PROXY_HANDLER )); private static final Set HOOK_CLASS_SUFFIX_NAMES = new HashSet(Collections.singletonList( ".dubbo.monitor.support.MonitorFilter" diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/models/policy/PropagatorNode.java b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/models/policy/PropagatorNode.java index 38e535745..e5ac751a8 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/models/policy/PropagatorNode.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/models/policy/PropagatorNode.java @@ -19,6 +19,7 @@ public PropagatorNode(Set sources, Set targets, this.commandArguments = commandArguments; } + @Override public PolicyNodeType getType() { return PolicyNodeType.PROPAGATOR; } diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/models/policy/SinkNode.java b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/models/policy/SinkNode.java index 355539eca..84d7e2d80 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/models/policy/SinkNode.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/models/policy/SinkNode.java @@ -12,6 +12,7 @@ public SinkNode(Set sources, MethodMatcher methodMatcher) { this.sources = sources; } + @Override public PolicyNodeType getType() { return PolicyNodeType.SINK; } diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/models/policy/SourceNode.java b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/models/policy/SourceNode.java index 0f9c8df9f..2485f1142 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/models/policy/SourceNode.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/models/policy/SourceNode.java @@ -11,6 +11,7 @@ public SourceNode(Set sources, Set targets, Method this.sources = sources; } + @Override public PolicyNodeType getType() { return PolicyNodeType.SOURCE; } diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/service/trace/DubboService.java b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/service/trace/DubboService.java index 8293826bb..4bc4926b2 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/service/trace/DubboService.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/service/trace/DubboService.java @@ -51,6 +51,4 @@ public static void solveSyncInvoke(MethodEvent event, Object invocation, String e.getMessage(), e.getCause() != null ? e.getCause().getMessage() : ""); } } - - } diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/vulscan/normal/AbstractNormalVulScan.java b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/vulscan/normal/AbstractNormalVulScan.java index 69c3aa026..146847fd5 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/vulscan/normal/AbstractNormalVulScan.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/vulscan/normal/AbstractNormalVulScan.java @@ -77,11 +77,12 @@ public static String getEncodedResponseHeader(String status, Map> headerItem : headers.entrySet()) { for (String v : headerItem.getValue()) { sb.append(headerItem.getKey()); diff --git a/dongtai-log/src/main/java/io/dongtai/log/ErrorCode.java b/dongtai-log/src/main/java/io/dongtai/log/ErrorCode.java index 1d6b31fcd..e06af044a 100644 --- a/dongtai-log/src/main/java/io/dongtai/log/ErrorCode.java +++ b/dongtai-log/src/main/java/io/dongtai/log/ErrorCode.java @@ -78,11 +78,13 @@ public enum ErrorCode { SPY_COLLECT_METHOD_FAILED(20303, "hookpoint collect method failed"), SPY_TRACE_FEIGN_INVOKE_FAILED(20304, "hookpoint trace feign invoke failed"), SPY_METHOD_POOL_OVER_CAPACITY(20305, "current request method pool size over capacity: {}"), - SPY_TRACE_DUBBO_INVOKE_FAILED(20306, "hookpoint trace dubbo invoke failed"), API_COLLECTOR_GET_API_THREAD_EXECUTE_FAILED(20311, "get api thread execute failed"), GRAPH_BUILD_AND_REPORT_FAILED(20321, "build and report request graph failed"), TAINT_COMMAND_GET_PARAMETERS_FAILED(20351, "taint command get {} parameters failed"), TAINT_COMMAND_RANGE_PROCESS_FAILED(20352, "taint command range process failed"), + SPY_TRACE_DUBBO_CONSUMER_INVOKE_FAILED(20361, "hookpoint trace dubbo consumer invoke failed"), + SPY_LEAVE_DUBBO_FAILED(20362, "hookpoint leave dubbo failed"), + SPY_COLLECT_DUBBO_FAILED(20363, "hookpoint collect dubbo {} failed"), // report & replay REPORT_SEND_FAILED(20401, "send report to {} error, report: {}"), diff --git a/dongtai-spy/src/main/java/java/lang/dongtai/NopSpy.java b/dongtai-spy/src/main/java/java/lang/dongtai/NopSpy.java index 275b82299..be25f349a 100644 --- a/dongtai-spy/src/main/java/java/lang/dongtai/NopSpy.java +++ b/dongtai-spy/src/main/java/java/lang/dongtai/NopSpy.java @@ -1,5 +1,6 @@ package java.lang.dongtai; +import java.net.InetSocketAddress; import java.util.*; public class NopSpy implements SpyDispatcher { @@ -28,7 +29,6 @@ public void leaveScope(int id) { */ @Override public void enterHttp() { - } /** @@ -40,7 +40,6 @@ public void enterHttp() { */ @Override public void leaveHttp(Object request, Object response) { - } /** @@ -54,6 +53,7 @@ public boolean isFirstLevelHttp() { return false; } + @Override public void collectHttpRequest(Object obj, Object req, Object resp, StringBuffer requestURL, String requestURI, String queryString, String method, String protocol, String scheme, String serverName, String contextPath, String remoteAddr, @@ -76,6 +76,31 @@ public void onServletOutputStreamWrite(String desc, Object stream, int b, byte[] public void onPrintWriterWrite(String desc, Object writer, int b, String s, char[] cs, int offset, int len) { } + @Override + public void enterDubbo() { + } + + @Override + public void leaveDubbo(Object request, Object response, Object result, byte status) { + } + + @Override + public boolean isFirstLevelDubbo() { + return false; + } + + @Override + public void collectDubboRequest(Object handler, Object channel, Object request, + String url, InetSocketAddress remoteAddress, + boolean isTwoWay, boolean isEvent, boolean isBroken, boolean isHeartbeat) { + } + + @Override + public void collectDubboRequestSource(Object handler, Object invocation, String methodName, + Object[] arguments, Map headers, + String hookClass, String hookMethod, String hookSign) { + } + /** * mark for enter Source Entry Point * diff --git a/dongtai-spy/src/main/java/java/lang/dongtai/SpyDispatcher.java b/dongtai-spy/src/main/java/java/lang/dongtai/SpyDispatcher.java index 07a281a9d..8d3c33abb 100644 --- a/dongtai-spy/src/main/java/java/lang/dongtai/SpyDispatcher.java +++ b/dongtai-spy/src/main/java/java/lang/dongtai/SpyDispatcher.java @@ -1,5 +1,6 @@ package java.lang.dongtai; +import java.net.InetSocketAddress; import java.util.*; public interface SpyDispatcher { @@ -48,6 +49,20 @@ void collectHttpRequest(Object obj, Object req, Object resp, StringBuffer reques void onPrintWriterWrite(String desc, Object writer, int b, String s, char[] cs, int offset, int len); + void enterDubbo(); + + void leaveDubbo(final Object request, final Object response, Object result, byte status); + + boolean isFirstLevelDubbo(); + + void collectDubboRequest(Object handler, Object channel, Object request, + String url, InetSocketAddress remoteAddress, + boolean isTwoWay, boolean isEvent, boolean isBroken, boolean isHeartbeat); + + void collectDubboRequestSource(Object handler, Object invocation, String methodName, + Object[] arguments, Map headers, + String hookClass, String hookMethod, String hookSign); + /** * mark for enter Source Entry Point * From 9c8b1ae16ee69ad87996643fe3e24d39a843893c Mon Sep 17 00:00:00 2001 From: lostsnow Date: Tue, 7 Mar 2023 10:45:30 +0800 Subject: [PATCH 4/7] add modern dubbo support --- .../core/bytecode/enhance/asm/AsmMethods.java | 11 ++- .../plugin/framework/dubbo/DispatchDubbo.java | 30 +++++-- .../dubbo/DubboExchangeChannelAdapter.java | 35 ++++++++ ...DubboExchangeChannelSendAdviceAdapter.java | 74 ++++++++++++++++ ...boExchangeHandleRequestAdviceAdapter.java} | 84 +++++++++++-------- ....java => DubboExchangeHandlerAdapter.java} | 16 ++-- ...ter.java => DubboProxyHandlerAdapter.java} | 16 ++-- ...DubboProxyHandlerInvokeAdviceAdapter.java} | 19 +++-- ...pter.java => DubboSyncHandlerAdapter.java} | 16 ++-- ... DubboSyncHandlerInvokeAdviceAdapter.java} | 17 ++-- .../handler/hookpoint/SpyDispatcherImpl.java | 35 ++++++-- .../hookpoint/controller/impl/DubboImpl.java | 21 +++-- .../hookpoint/graphy/GraphBuilder.java | 6 +- .../models/policy/PolicyManager.java | 14 ++-- .../main/java/java/lang/dongtai/NopSpy.java | 8 +- .../java/java/lang/dongtai/SpyDispatcher.java | 6 +- 16 files changed, 308 insertions(+), 100 deletions(-) create mode 100644 dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DubboExchangeChannelAdapter.java create mode 100644 dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DubboExchangeChannelSendAdviceAdapter.java rename dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/{LegacyDubboExchangeHandleRequestAdviceAdapter.java => DubboExchangeHandleRequestAdviceAdapter.java} (62%) rename dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/{LegacyDubboExchangeHandlerAdapter.java => DubboExchangeHandlerAdapter.java} (51%) rename dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/{LegacyDubboProxyHandlerAdapter.java => DubboProxyHandlerAdapter.java} (55%) rename dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/{LegacyDubboProxyHandlerInvokeAdviceAdapter.java => DubboProxyHandlerInvokeAdviceAdapter.java} (68%) rename dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/{LegacyDubboSyncHandlerAdapter.java => DubboSyncHandlerAdapter.java} (55%) rename dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/{LegacyDubboSyncHandlerInvokeAdviceAdapter.java => DubboSyncHandlerInvokeAdviceAdapter.java} (79%) diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/asm/AsmMethods.java b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/asm/AsmMethods.java index 67dfa1ed7..c043446f1 100755 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/asm/AsmMethods.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/asm/AsmMethods.java @@ -140,9 +140,7 @@ static Method getAsmMethod(final Class clazz, SpyDispatcher.class, "leaveDubbo", Object.class, - Object.class, - Object.class, - byte.class + Object.class ); Method SPY$isFirstLevelDubbo = InnerHelper.getAsmMethod( SpyDispatcher.class, @@ -175,6 +173,13 @@ static Method getAsmMethod(final Class clazz, String.class ); + Method SPY$collectDubboResponse = InnerHelper.getAsmMethod( + SpyDispatcher.class, + "collectDubboResponse", + Object.class, + byte.class + ); + Method SPY$enterSource = InnerHelper.getAsmMethod( SpyDispatcher.class, "enterSource" diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DispatchDubbo.java b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DispatchDubbo.java index 5c626e07c..5edba1d9f 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DispatchDubbo.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DispatchDubbo.java @@ -6,20 +6,32 @@ import org.objectweb.asm.ClassVisitor; public class DispatchDubbo implements DispatchPlugin { - public static final String LEGACY_DUBBO_SYNC_HANDLER = " com.alibaba.dubbo.rpc.listener.ListenerInvokerWrapper".substring(1); - public static final String LEGACY_DUBBO_EXCHANGE_HANDLER = " com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeHandler".substring(1); - public static final String LEGACY_DUBBO_PROXY_HANDLER = " com.alibaba.dubbo.rpc.proxy.AbstractProxyInvoker".substring(1); + public static final String ALIBABA_DUBBO_SYNC_HANDLER = " com.alibaba.dubbo.rpc.listener.ListenerInvokerWrapper".substring(1); + public static final String APACHE_DUBBO_SYNC_HANDLER = " org.apache.dubbo.rpc.listener.ListenerInvokerWrapper".substring(1); + public static final String ALIBABA_DUBBO_EXCHANGE_HANDLER = " com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeHandler".substring(1); + public static final String APACHE_DUBBO_EXCHANGE_HANDLER = " org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler".substring(1); + public static final String APACHE_DUBBO_EXCHANGE_CHANNEL = " org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeChannel".substring(1); + public static final String ALIBABA_DUBBO_PROXY_HANDLER = " com.alibaba.dubbo.rpc.proxy.AbstractProxyInvoker".substring(1); + public static final String APACHE_DUBBO_PROXY_HANDLER = " org.apache.dubbo.rpc.proxy.AbstractProxyInvoker".substring(1); @Override public ClassVisitor dispatch(ClassVisitor classVisitor, ClassContext context, Policy policy) { String className = context.getClassName(); - if (LEGACY_DUBBO_SYNC_HANDLER.equals(className)) { - classVisitor = new LegacyDubboSyncHandlerAdapter(classVisitor, context); - } else if (LEGACY_DUBBO_EXCHANGE_HANDLER.equals(className)) { - classVisitor = new LegacyDubboExchangeHandlerAdapter(classVisitor, context); - } else if (LEGACY_DUBBO_PROXY_HANDLER.equals(className)) { - classVisitor = new LegacyDubboProxyHandlerAdapter(classVisitor, context); + if (ALIBABA_DUBBO_SYNC_HANDLER.equals(className)) { + classVisitor = new DubboSyncHandlerAdapter(classVisitor, context, " com.alibaba".substring(1)); + } else if (APACHE_DUBBO_SYNC_HANDLER.equals(className)) { + classVisitor = new DubboSyncHandlerAdapter(classVisitor, context, " org.apache".substring(1)); + } else if (ALIBABA_DUBBO_EXCHANGE_HANDLER.equals(className)) { + classVisitor = new DubboExchangeHandlerAdapter(classVisitor, context, " com.alibaba".substring(1)); + } else if (APACHE_DUBBO_EXCHANGE_HANDLER.equals(className)) { + classVisitor = new DubboExchangeHandlerAdapter(classVisitor, context, " org.apache".substring(1)); + } else if (APACHE_DUBBO_EXCHANGE_CHANNEL.equals(className)) { + classVisitor = new DubboExchangeChannelAdapter(classVisitor, context, " org.apache".substring(1)); + } else if (ALIBABA_DUBBO_PROXY_HANDLER.equals(className)) { + classVisitor = new DubboProxyHandlerAdapter(classVisitor, context, " com.alibaba".substring(1)); + } else if (APACHE_DUBBO_PROXY_HANDLER.equals(className)) { + classVisitor = new DubboProxyHandlerAdapter(classVisitor, context, " org.apache".substring(1)); } return classVisitor; diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DubboExchangeChannelAdapter.java b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DubboExchangeChannelAdapter.java new file mode 100644 index 000000000..0b23b4082 --- /dev/null +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DubboExchangeChannelAdapter.java @@ -0,0 +1,35 @@ +package io.dongtai.iast.core.bytecode.enhance.plugin.framework.dubbo; + +import io.dongtai.iast.core.bytecode.enhance.ClassContext; +import io.dongtai.iast.core.bytecode.enhance.plugin.AbstractClassVisitor; +import io.dongtai.iast.core.utils.AsmUtils; +import io.dongtai.log.DongTaiLog; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; + +public class DubboExchangeChannelAdapter extends AbstractClassVisitor { + public static final String DUBBO_EXCHANGE_CHANNEL_SEND = "{package}.dubbo.remoting.exchange.support.header.HeaderExchangeChannel.send(java.lang.Object)"; + + private final String packageName; + private final String sendSign; + + public DubboExchangeChannelAdapter(ClassVisitor classVisitor, ClassContext context, String packageName) { + super(classVisitor, context); + this.packageName = packageName; + this.sendSign = DUBBO_EXCHANGE_CHANNEL_SEND.replace("{package}", this.packageName); + } + + @Override + public MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) { + MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); + String signCode = AsmUtils.buildSignature(context.getClassName(), name, desc); + + if (this.sendSign.equals(signCode)) { + DongTaiLog.debug("Adding dubbo provider response tracking by {}", signCode); + mv = new DubboExchangeChannelSendAdviceAdapter(mv, access, name, desc, signCode, + this.context, this.packageName); + setTransformed(); + } + return mv; + } +} diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DubboExchangeChannelSendAdviceAdapter.java b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DubboExchangeChannelSendAdviceAdapter.java new file mode 100644 index 000000000..ddaa64e24 --- /dev/null +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DubboExchangeChannelSendAdviceAdapter.java @@ -0,0 +1,74 @@ +package io.dongtai.iast.core.bytecode.enhance.plugin.framework.dubbo; + +import io.dongtai.iast.core.bytecode.enhance.ClassContext; +import io.dongtai.iast.core.bytecode.enhance.plugin.AbstractAdviceAdapter; +import org.objectweb.asm.*; +import org.objectweb.asm.commons.Method; + +public class DubboExchangeChannelSendAdviceAdapter extends AbstractAdviceAdapter { + private static final Method GET_RESULT_METHOD = Method.getMethod("java.lang.Object getResult()"); + private static final Method GET_STATUS_METHOD = Method.getMethod("byte getStatus()"); + + private final String packageName; + private final Type objectType; + private final Type responseType; + + protected DubboExchangeChannelSendAdviceAdapter(MethodVisitor mv, int access, String name, String desc, + String signature, ClassContext context, String packageName) { + super(mv, access, name, desc, context, "dubbo", signature); + this.packageName = packageName; + String packageDesc = packageName.replace(".", "/"); + this.responseType = Type.getObjectType(packageDesc + "/dubbo/remoting/exchange/Response"); + this.objectType = Type.getObjectType("java/lang/Object"); + } + + @Override + protected void before() { + mark(tryLabel); + Label elseLabel = new Label(); + + isFirstLevelDubbo(); + mv.visitJumpInsn(EQ, elseLabel); + + collectDubboResponse(); + + mark(elseLabel); + } + + @Override + protected void after(int opcode) { + } + + private void isFirstLevelDubbo() { + invokeStatic(ASM_TYPE_SPY_HANDLER, SPY_HANDLER$getDispatcher); + invokeInterface(ASM_TYPE_SPY_DISPATCHER, SPY$isFirstLevelDubbo); + } + + private void collectDubboResponse() { + Label tryL = new Label(); + Label catchL = new Label(); + Label exHandlerL = new Label(); + visitTryCatchBlock(tryL, catchL, exHandlerL, ASM_TYPE_THROWABLE.getInternalName()); + visitLabel(tryL); + + + int respLocal = newLocal(this.responseType); + loadArg(0); + checkCast(this.responseType); + storeLocal(respLocal); + + invokeStatic(ASM_TYPE_SPY_HANDLER, SPY_HANDLER$getDispatcher); + loadLocal(respLocal); + invokeVirtual(this.responseType, GET_RESULT_METHOD); + loadLocal(respLocal); + invokeVirtual(this.responseType, GET_STATUS_METHOD); + invokeInterface(ASM_TYPE_SPY_DISPATCHER, SPY$collectDubboResponse); + + visitLabel(catchL); + Label endL = new Label(); + visitJumpInsn(GOTO, endL); + visitLabel(exHandlerL); + visitVarInsn(ASTORE, this.nextLocal); + visitLabel(endL); + } +} diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboExchangeHandleRequestAdviceAdapter.java b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DubboExchangeHandleRequestAdviceAdapter.java similarity index 62% rename from dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboExchangeHandleRequestAdviceAdapter.java rename to dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DubboExchangeHandleRequestAdviceAdapter.java index 12fefb307..7f580c959 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboExchangeHandleRequestAdviceAdapter.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DubboExchangeHandleRequestAdviceAdapter.java @@ -5,8 +5,7 @@ import org.objectweb.asm.*; import org.objectweb.asm.commons.Method; -public class LegacyDubboExchangeHandleRequestAdviceAdapter extends AbstractAdviceAdapter { - private static final Method GET_URL_METHOD = Method.getMethod(" com.alibaba.dubbo.common.URL getUrl()".substring(1)); +public class DubboExchangeHandleRequestAdviceAdapter extends AbstractAdviceAdapter { private static final Method URL_TO_STRING_METHOD = Method.getMethod("java.lang.String toString()"); private static final Method GET_REMOTE_ADDRESS_METHOD = Method.getMethod("java.net.InetSocketAddress getRemoteAddress()"); private static final Method IS_TWO_WAY_METHOD = Method.getMethod("boolean isTwoWay()"); @@ -16,19 +15,31 @@ public class LegacyDubboExchangeHandleRequestAdviceAdapter extends AbstractAdvic private static final Method GET_RESULT_METHOD = Method.getMethod("java.lang.Object getResult()"); private static final Method GET_STATUS_METHOD = Method.getMethod("byte getStatus()"); + private final String packageName; private final Type endpointType; private final Type urlType; private final Type channelType; private final Type requestType; private final Type responseType; + private final Method getUrlMethod; - protected LegacyDubboExchangeHandleRequestAdviceAdapter(MethodVisitor mv, int access, String name, String desc, String signature, ClassContext context) { + protected DubboExchangeHandleRequestAdviceAdapter(MethodVisitor mv, int access, String name, String desc, + String signature, ClassContext context, String packageName) { super(mv, access, name, desc, context, "dubbo", signature); - this.endpointType = Type.getObjectType(" com/alibaba/dubbo/remoting/Endpoint".substring(1)); - this.urlType = Type.getObjectType(" com/alibaba/dubbo/common/URL".substring(1)); - this.channelType = Type.getObjectType(" com/alibaba/dubbo/remoting/Channel".substring(1)); - this.requestType = Type.getObjectType(" com/alibaba/dubbo/remoting/exchange/Request".substring(1)); - this.responseType = Type.getObjectType(" com/alibaba/dubbo/remoting/exchange/Response".substring(1)); + this.packageName = packageName; + String packageDesc = packageName.replace(".", "/"); + this.endpointType = Type.getObjectType(packageDesc + "/dubbo/remoting/Endpoint"); + this.urlType = Type.getObjectType(packageDesc + "/dubbo/common/URL"); + this.channelType = Type.getObjectType(packageDesc + "/dubbo/remoting/Channel"); + this.requestType = Type.getObjectType(packageDesc + "/dubbo/remoting/exchange/Request"); + if (" com.alibaba".substring(1).equals(packageName)) { + this.responseType = Type.getObjectType(packageDesc + "/dubbo/remoting/exchange/Response"); + } else { + // org.apache.dubbo use HeaderExchangeChannel to track response + this.responseType = null; + } + + this.getUrlMethod = Method.getMethod(packageName + ".dubbo.common.URL getUrl()"); } @Override @@ -47,13 +58,13 @@ protected void before() { @Override protected void after(int opcode) { - // if (opcode != ATHROW) { - // Label elseLabel = new Label(); - // isFirstLevelDubbo(); - // mv.visitJumpInsn(EQ, elseLabel); - // collectDubboResponse(opcode); - // mark(elseLabel); - // } + if (this.responseType != null && opcode != ATHROW) { + Label elseLabel = new Label(); + isFirstLevelDubbo(); + mv.visitJumpInsn(EQ, elseLabel); + collectDubboResponse(opcode); + mark(elseLabel); + } leaveDubbo(opcode); } @@ -64,26 +75,9 @@ private void enterDubbo() { } private void leaveDubbo(int opcode) { - int retLocal = newLocal(ASM_TYPE_OBJECT); - if (!isThrow(opcode)) { - loadReturn(opcode); - } else { - pushNull(); - } - storeLocal(retLocal); invokeStatic(ASM_TYPE_SPY_HANDLER, SPY_HANDLER$getDispatcher); + loadArg(0); loadArg(1); - loadLocal(retLocal); - if (!isThrow(opcode)) { - loadLocal(retLocal); - invokeVirtual(this.responseType, GET_RESULT_METHOD); - loadLocal(retLocal); - invokeVirtual(this.responseType, GET_STATUS_METHOD); - } else { - pushNull(); - byte b = 0; - push(b); - } invokeInterface(ASM_TYPE_SPY_DISPATCHER, SPY$leaveDubbo); } @@ -104,7 +98,7 @@ private void collectDubboRequest() { loadArg(0); loadArg(1); loadArg(0); - invokeInterface(this.endpointType, GET_URL_METHOD); + invokeInterface(this.endpointType, this.getUrlMethod); invokeVirtual(this.urlType, URL_TO_STRING_METHOD); loadArg(0); invokeInterface(this.channelType, GET_REMOTE_ADDRESS_METHOD); @@ -122,7 +116,27 @@ private void collectDubboRequest() { Label endL = new Label(); visitJumpInsn(GOTO, endL); visitLabel(exHandlerL); - visitVarInsn(ASTORE, this.nextLocal); + int nextL = newLocal(ASM_TYPE_OBJECT); + storeLocal(nextL); visitLabel(endL); } + + private void collectDubboResponse(int opcode) { + int retLocal = newLocal(ASM_TYPE_OBJECT); + loadReturn(opcode); + storeLocal(retLocal); + + Label nonNullLabel = new Label(); + loadLocal(retLocal); + ifNull(nonNullLabel); + + invokeStatic(ASM_TYPE_SPY_HANDLER, SPY_HANDLER$getDispatcher); + loadLocal(retLocal); + invokeVirtual(this.responseType, GET_RESULT_METHOD); + loadLocal(retLocal); + invokeVirtual(this.responseType, GET_STATUS_METHOD); + invokeInterface(ASM_TYPE_SPY_DISPATCHER, SPY$collectDubboResponse); + + mark(nonNullLabel); + } } diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboExchangeHandlerAdapter.java b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DubboExchangeHandlerAdapter.java similarity index 51% rename from dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboExchangeHandlerAdapter.java rename to dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DubboExchangeHandlerAdapter.java index dedba4cdc..01b7b6e5a 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboExchangeHandlerAdapter.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DubboExchangeHandlerAdapter.java @@ -7,11 +7,16 @@ import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.MethodVisitor; -public class LegacyDubboExchangeHandlerAdapter extends AbstractClassVisitor { - public static final String LEGACY_DUBBO_EXCHANGE_HANDLE_REQUEST = " com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.handleRequest(com.alibaba.dubbo.remoting.exchange.ExchangeChannel,com.alibaba.dubbo.remoting.exchange.Request)".substring(1); +public class DubboExchangeHandlerAdapter extends AbstractClassVisitor { + public static final String DUBBO_EXCHANGE_HANDLE_REQUEST = "{package}.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.handleRequest({package}.dubbo.remoting.exchange.ExchangeChannel,{package}.dubbo.remoting.exchange.Request)"; - public LegacyDubboExchangeHandlerAdapter(ClassVisitor classVisitor, ClassContext context) { + private final String packageName; + private final String handleRequestSign; + + public DubboExchangeHandlerAdapter(ClassVisitor classVisitor, ClassContext context, String packageName) { super(classVisitor, context); + this.packageName = packageName; + this.handleRequestSign = DUBBO_EXCHANGE_HANDLE_REQUEST.replace("{package}", this.packageName); } @Override @@ -19,9 +24,10 @@ public MethodVisitor visitMethod(final int access, final String name, final Stri MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); String signCode = AsmUtils.buildSignature(context.getClassName(), name, desc); - if (LEGACY_DUBBO_EXCHANGE_HANDLE_REQUEST.equals(signCode)) { + if (this.handleRequestSign.equals(signCode)) { DongTaiLog.debug("Adding dubbo provider tracking by {}", signCode); - mv = new LegacyDubboExchangeHandleRequestAdviceAdapter(mv, access, name, desc, signCode, this.context); + mv = new DubboExchangeHandleRequestAdviceAdapter(mv, access, name, desc, signCode, + this.context, this.packageName); setTransformed(); } return mv; diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboProxyHandlerAdapter.java b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DubboProxyHandlerAdapter.java similarity index 55% rename from dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboProxyHandlerAdapter.java rename to dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DubboProxyHandlerAdapter.java index b0079c7c7..f4f288ed4 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboProxyHandlerAdapter.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DubboProxyHandlerAdapter.java @@ -7,11 +7,16 @@ import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.MethodVisitor; -public class LegacyDubboProxyHandlerAdapter extends AbstractClassVisitor { - public static final String LEGACY_DUBBO_PROXY_HANDLER_INVOKE = " com.alibaba.dubbo.rpc.proxy.AbstractProxyInvoker.invoke(com.alibaba.dubbo.rpc.Invocation)".substring(1); +public class DubboProxyHandlerAdapter extends AbstractClassVisitor { + public static final String DUBBO_PROXY_HANDLER_INVOKE = "{package}.dubbo.rpc.proxy.AbstractProxyInvoker.invoke({package}.dubbo.rpc.Invocation)"; - public LegacyDubboProxyHandlerAdapter(ClassVisitor classVisitor, ClassContext context) { + private final String packageName; + private final String fullSign; + + public DubboProxyHandlerAdapter(ClassVisitor classVisitor, ClassContext context, String packageName) { super(classVisitor, context); + this.packageName = packageName; + this.fullSign = DUBBO_PROXY_HANDLER_INVOKE.replace("{package}", this.packageName); } @Override @@ -19,9 +24,10 @@ public MethodVisitor visitMethod(final int access, final String name, final Stri MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); String signCode = AsmUtils.buildSignature(context.getClassName(), name, desc); - if (LEGACY_DUBBO_PROXY_HANDLER_INVOKE.equals(signCode)) { + if (this.fullSign.equals(signCode)) { DongTaiLog.debug("Adding dubbo provider source tracking by {}", signCode); - mv = new LegacyDubboProxyHandlerInvokeAdviceAdapter(mv, access, name, desc, signCode, this.context); + mv = new DubboProxyHandlerInvokeAdviceAdapter(mv, access, name, desc, signCode, + this.context, this.packageName); setTransformed(); } return mv; diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboProxyHandlerInvokeAdviceAdapter.java b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DubboProxyHandlerInvokeAdviceAdapter.java similarity index 68% rename from dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboProxyHandlerInvokeAdviceAdapter.java rename to dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DubboProxyHandlerInvokeAdviceAdapter.java index ab1dd8fc1..dee54fc08 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboProxyHandlerInvokeAdviceAdapter.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DubboProxyHandlerInvokeAdviceAdapter.java @@ -6,16 +6,25 @@ import org.objectweb.asm.*; import org.objectweb.asm.commons.Method; -public class LegacyDubboProxyHandlerInvokeAdviceAdapter extends AbstractAdviceAdapter { +public class DubboProxyHandlerInvokeAdviceAdapter extends AbstractAdviceAdapter { private static final Method GET_ARGUMENTS_METHOD = Method.getMethod("java.lang.Object[] getArguments()"); - private static final Method GET_GETATTACHMENTS_METHOD = Method.getMethod("java.util.Map getAttachments()"); private static final Method GET_METHOD_NAME_METHOD = Method.getMethod("java.lang.String getMethodName()"); + private final String packageName; private final Type invocationType; + private final Method getAttachmentsMethod; - protected LegacyDubboProxyHandlerInvokeAdviceAdapter(MethodVisitor mv, int access, String name, String desc, String signature, ClassContext context) { + protected DubboProxyHandlerInvokeAdviceAdapter(MethodVisitor mv, int access, String name, String desc, + String signature, ClassContext context, String packageName) { super(mv, access, name, desc, context, "dubbo", signature); - this.invocationType = Type.getObjectType(" com/alibaba/dubbo/rpc/Invocation".substring(1)); + this.packageName = packageName; + String packageDesc = packageName.replace(".", "/"); + this.invocationType = Type.getObjectType(packageDesc + "/dubbo/rpc/Invocation"); + if (" com.alibaba".substring(1).equals(packageName)) { + this.getAttachmentsMethod = Method.getMethod("java.util.Map getAttachments()"); + } else { + this.getAttachmentsMethod = Method.getMethod("java.util.Map getObjectAttachments()"); + } } @Override @@ -51,7 +60,7 @@ private void collectDubboRequestSource() { loadArg(0); invokeInterface(this.invocationType, GET_ARGUMENTS_METHOD); loadArg(0); - invokeInterface(this.invocationType, GET_GETATTACHMENTS_METHOD); + invokeInterface(this.invocationType, this.getAttachmentsMethod); push(this.classContext.getClassName()); push(this.name); push(this.signature); diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboSyncHandlerAdapter.java b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DubboSyncHandlerAdapter.java similarity index 55% rename from dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboSyncHandlerAdapter.java rename to dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DubboSyncHandlerAdapter.java index 698d685bf..fdc6aa3a1 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboSyncHandlerAdapter.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DubboSyncHandlerAdapter.java @@ -7,11 +7,16 @@ import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.MethodVisitor; -public class LegacyDubboSyncHandlerAdapter extends AbstractClassVisitor { - private static final String LEGACY_DUBBO_SYNC_HANDLER_INVOKE = " com.alibaba.dubbo.rpc.listener.ListenerInvokerWrapper.invoke(com.alibaba.dubbo.rpc.Invocation)".substring(1); +public class DubboSyncHandlerAdapter extends AbstractClassVisitor { + private static final String DUBBO_SYNC_HANDLER_INVOKE = "{package}.dubbo.rpc.listener.ListenerInvokerWrapper.invoke({package}.dubbo.rpc.Invocation)"; - public LegacyDubboSyncHandlerAdapter(ClassVisitor classVisitor, ClassContext context) { + private final String packageName; + private final String fullSign; + + public DubboSyncHandlerAdapter(ClassVisitor classVisitor, ClassContext context, String packageName) { super(classVisitor, context); + this.packageName = packageName; + this.fullSign = DUBBO_SYNC_HANDLER_INVOKE.replace("{package}", this.packageName); } @Override @@ -19,9 +24,10 @@ public MethodVisitor visitMethod(final int access, final String name, final Stri MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); String signCode = AsmUtils.buildSignature(context.getClassName(), name, desc); - if (LEGACY_DUBBO_SYNC_HANDLER_INVOKE.equals(signCode)) { + if (this.fullSign.equals(signCode)) { DongTaiLog.debug("Adding dubbo consumer tracking by {}", signCode); - mv = new LegacyDubboSyncHandlerInvokeAdviceAdapter(mv, access, name, desc, signCode, this.context); + mv = new DubboSyncHandlerInvokeAdviceAdapter(mv, access, name, desc, signCode, + this.context, this.packageName); setTransformed(); } return mv; diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboSyncHandlerInvokeAdviceAdapter.java b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DubboSyncHandlerInvokeAdviceAdapter.java similarity index 79% rename from dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboSyncHandlerInvokeAdviceAdapter.java rename to dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DubboSyncHandlerInvokeAdviceAdapter.java index a92c18bb8..ae61c079f 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/LegacyDubboSyncHandlerInvokeAdviceAdapter.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/bytecode/enhance/plugin/framework/dubbo/DubboSyncHandlerInvokeAdviceAdapter.java @@ -5,22 +5,27 @@ import org.objectweb.asm.*; import org.objectweb.asm.commons.Method; -public class LegacyDubboSyncHandlerInvokeAdviceAdapter extends AbstractAdviceAdapter { - private static final Method GET_URL_METHOD = Method.getMethod(" com.alibaba.dubbo.common.URL getUrl()".substring(1)); +public class DubboSyncHandlerInvokeAdviceAdapter extends AbstractAdviceAdapter { + private final Method GET_URL_METHOD; private static final Method GET_ARGUMENTS_METHOD = Method.getMethod("java.lang.Object[] getArguments()"); private static final Method GET_GETATTACHMENTS_METHOD = Method.getMethod("java.util.Map getAttachments()"); private static final Method URL_TO_STRING_METHOD = Method.getMethod("java.lang.String toString()"); + private final String packageName; private Label exHandler; private final Type handlerType; private final Type urlType; private final Type invocationType; - protected LegacyDubboSyncHandlerInvokeAdviceAdapter(MethodVisitor mv, int access, String name, String desc, String signature, ClassContext context) { + protected DubboSyncHandlerInvokeAdviceAdapter(MethodVisitor mv, int access, String name, String desc, + String signature, ClassContext context, String packageName) { super(mv, access, name, desc, context, "dubbo", signature); - this.handlerType = Type.getObjectType(" com/alibaba/dubbo/rpc/listener/ListenerInvokerWrapper".substring(1)); - this.invocationType = Type.getObjectType(" com/alibaba/dubbo/rpc/Invocation".substring(1)); - this.urlType = Type.getObjectType(" com/alibaba/dubbo/common/URL".substring(1)); + GET_URL_METHOD = Method.getMethod(packageName + ".dubbo.common.URL getUrl()"); + this.packageName = packageName; + String packageDesc = packageName.replace(".", "/"); + this.handlerType = Type.getObjectType(packageDesc + "/dubbo/rpc/listener/ListenerInvokerWrapper"); + this.invocationType = Type.getObjectType(packageDesc + "/dubbo/rpc/Invocation"); + this.urlType = Type.getObjectType(packageDesc + "/dubbo/common/URL"); } @Override diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/SpyDispatcherImpl.java b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/SpyDispatcherImpl.java index c65ca60a6..f51c250b5 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/SpyDispatcherImpl.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/SpyDispatcherImpl.java @@ -124,7 +124,7 @@ public void leaveHttp(Object request, Object response) { if (!ScopeManager.SCOPE_TRACKER.getScope(Scope.HTTP_REQUEST).in() && ScopeManager.SCOPE_TRACKER.getScope(Scope.HTTP_ENTRY).in()) { EngineManager.maintainRequestCount(); - GraphBuilder.buildAndReport(request, response); + GraphBuilder.buildAndReport(); EngineManager.cleanThreadState(); } } catch (Throwable e) { @@ -280,22 +280,17 @@ public void enterDubbo() { } @Override - public void leaveDubbo(Object request, Object response, Object result, byte status) { + public void leaveDubbo(Object channel, Object request) { if (!EngineManager.isEngineRunning()) { EngineManager.cleanThreadState(); return; } try { - if (ScopeManager.SCOPE_TRACKER.getScope(Scope.DUBBO_REQUEST).isFirst() - && ScopeManager.SCOPE_TRACKER.getScope(Scope.DUBBO_ENTRY).in()) { - DubboImpl.collectDubboResponse(result, status); - } - ScopeManager.SCOPE_TRACKER.getScope(Scope.DUBBO_REQUEST).leave(); if (!ScopeManager.SCOPE_TRACKER.getScope(Scope.DUBBO_REQUEST).in() && ScopeManager.SCOPE_TRACKER.getScope(Scope.DUBBO_ENTRY).in()) { EngineManager.maintainRequestCount(); - GraphBuilder.buildAndReport(request, response); + GraphBuilder.buildAndReport(); EngineManager.cleanThreadState(); } } catch (Throwable e) { @@ -341,7 +336,7 @@ public void collectDubboRequest(Object handler, Object channel, Object request, @Override public void collectDubboRequestSource(Object handler, Object invocation, String methodName, - Object[] arguments, Map headers, + Object[] arguments, Map headers, String hookClass, String hookMethod, String hookSign) { try { ScopeManager.SCOPE_TRACKER.getPolicyScope().enterAgent(); @@ -359,6 +354,28 @@ public void collectDubboRequestSource(Object handler, Object invocation, String } } + @Override + public void collectDubboResponse(Object result, byte status) { + try { + ScopeManager.SCOPE_TRACKER.getPolicyScope().enterAgent(); + + if (!EngineManager.isEngineRunning()) { + return; + } + + if (!ScopeManager.SCOPE_TRACKER.getScope(Scope.DUBBO_REQUEST).isFirst() + || !ScopeManager.SCOPE_TRACKER.getScope(Scope.DUBBO_ENTRY).in()) { + return; + } + + DubboImpl.collectDubboResponse(result, status); + } catch (Throwable e) { + DongTaiLog.warn(ErrorCode.SPY_COLLECT_DUBBO_FAILED, "response", e); + } finally { + ScopeManager.SCOPE_TRACKER.getPolicyScope().leaveAgent(); + } + } + /** * mark for enter Source Entry Point * diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/controller/impl/DubboImpl.java b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/controller/impl/DubboImpl.java index e54cc8e09..feb048958 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/controller/impl/DubboImpl.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/controller/impl/DubboImpl.java @@ -43,7 +43,7 @@ public static void solveDubboRequest(Object handler, Object channel, Object requ public static void collectDubboRequestSource(Object handler, Object invocation, String methodName, - Object[] arguments, Map headers, + Object[] arguments, Map headers, String hookClass, String hookMethod, String hookSign, AtomicInteger invokeIdSequencer) { if (arguments == null || arguments.length == 0) { @@ -71,13 +71,24 @@ public static void collectDubboRequestSource(Object handler, Object invocation, if (arguments != null && arguments.length > 0) { TaintPoolUtils.trackObject(event, sourceNode, arguments, 0); } - if (headers != null && !headers.isEmpty()) { + + Map sHeaders = new HashMap(); + if (headers != null) { + for (Map.Entry entry : headers.entrySet()) { + if (entry.getValue() == null) { + continue; + } + sHeaders.put(entry.getKey(), entry.getValue().toString()); + } + } + + if (!sHeaders.isEmpty()) { String traceIdKey = ContextManager.getHeaderKey(); if (headers.containsKey(traceIdKey)) { - ContextManager.parseTraceId(headers.get(traceIdKey)); + ContextManager.parseTraceId(sHeaders.get(traceIdKey)); } else { String newTraceId = ContextManager.currentTraceId(); - headers.put(traceIdKey, newTraceId); + sHeaders.put(traceIdKey, newTraceId); } } @@ -89,7 +100,7 @@ public static void collectDubboRequestSource(Object handler, Object invocation, event.setObjectValue(handler, false); event.setTaintPositions(sourceNode.getSources(), sourceNode.getTargets()); - requestMeta.put("headers", headers); + requestMeta.put("headers", sHeaders); JSONArray arr = new JSONArray(); for (Object arg : arguments) { arr.put(event.obj2String(arg)); diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/graphy/GraphBuilder.java b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/graphy/GraphBuilder.java index d4c09ede0..e368173fa 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/graphy/GraphBuilder.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/graphy/GraphBuilder.java @@ -25,11 +25,11 @@ public class GraphBuilder { private static String URL; private static String URI; - public static void buildAndReport(Object request, Object response) { + public static void buildAndReport() { try { ScopeManager.SCOPE_TRACKER.getPolicyScope().enterAgent(); List nodeList = build(); - String report = convertToReport(nodeList, request, response); + String report = convertToReport(nodeList); if (report == null) { return; } @@ -56,7 +56,7 @@ public static List build() { return nodeList; } - public static String convertToReport(List nodeList, Object request, Object response) { + public static String convertToReport(List nodeList) { Map requestMeta = EngineManager.REQUEST_CONTEXT.get(); JSONObject report = new JSONObject(); diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/models/policy/PolicyManager.java b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/models/policy/PolicyManager.java index 23dd0e723..764c022ce 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/models/policy/PolicyManager.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/models/policy/PolicyManager.java @@ -30,13 +30,15 @@ public class PolicyManager { " javax.servlet.http.Cookie".substring(1), " org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker".substring(1), DispatchFeign.FEIGN_SYNC_HANDLER, - DispatchDubbo.LEGACY_DUBBO_SYNC_HANDLER, - DispatchDubbo.LEGACY_DUBBO_EXCHANGE_HANDLER, - DispatchDubbo.LEGACY_DUBBO_PROXY_HANDLER - )); - private static final Set HOOK_CLASS_SUFFIX_NAMES = new HashSet(Collections.singletonList( - ".dubbo.monitor.support.MonitorFilter" + DispatchDubbo.ALIBABA_DUBBO_SYNC_HANDLER, + DispatchDubbo.APACHE_DUBBO_SYNC_HANDLER, + DispatchDubbo.ALIBABA_DUBBO_EXCHANGE_HANDLER, + DispatchDubbo.APACHE_DUBBO_EXCHANGE_HANDLER, + DispatchDubbo.APACHE_DUBBO_EXCHANGE_CHANNEL, + DispatchDubbo.ALIBABA_DUBBO_PROXY_HANDLER, + DispatchDubbo.APACHE_DUBBO_PROXY_HANDLER )); + private static final Set HOOK_CLASS_SUFFIX_NAMES = new HashSet(); public Policy getPolicy() { return this.policy; diff --git a/dongtai-spy/src/main/java/java/lang/dongtai/NopSpy.java b/dongtai-spy/src/main/java/java/lang/dongtai/NopSpy.java index be25f349a..fe24c161b 100644 --- a/dongtai-spy/src/main/java/java/lang/dongtai/NopSpy.java +++ b/dongtai-spy/src/main/java/java/lang/dongtai/NopSpy.java @@ -81,7 +81,7 @@ public void enterDubbo() { } @Override - public void leaveDubbo(Object request, Object response, Object result, byte status) { + public void leaveDubbo(Object channel, Object request) { } @Override @@ -97,10 +97,14 @@ public void collectDubboRequest(Object handler, Object channel, Object request, @Override public void collectDubboRequestSource(Object handler, Object invocation, String methodName, - Object[] arguments, Map headers, + Object[] arguments, Map headers, String hookClass, String hookMethod, String hookSign) { } + @Override + public void collectDubboResponse(Object result, byte status) { + } + /** * mark for enter Source Entry Point * diff --git a/dongtai-spy/src/main/java/java/lang/dongtai/SpyDispatcher.java b/dongtai-spy/src/main/java/java/lang/dongtai/SpyDispatcher.java index 8d3c33abb..df572fee2 100644 --- a/dongtai-spy/src/main/java/java/lang/dongtai/SpyDispatcher.java +++ b/dongtai-spy/src/main/java/java/lang/dongtai/SpyDispatcher.java @@ -51,7 +51,7 @@ void collectHttpRequest(Object obj, Object req, Object resp, StringBuffer reques void enterDubbo(); - void leaveDubbo(final Object request, final Object response, Object result, byte status); + void leaveDubbo(Object channel, Object request); boolean isFirstLevelDubbo(); @@ -60,9 +60,11 @@ void collectDubboRequest(Object handler, Object channel, Object request, boolean isTwoWay, boolean isEvent, boolean isBroken, boolean isHeartbeat); void collectDubboRequestSource(Object handler, Object invocation, String methodName, - Object[] arguments, Map headers, + Object[] arguments, Map headers, String hookClass, String hookMethod, String hookSign); + void collectDubboResponse(Object result, byte status); + /** * mark for enter Source Entry Point * From 8a23adb1746c260f91abe6a4dd3fe02f4005282c Mon Sep 17 00:00:00 2001 From: lostsnow Date: Tue, 7 Mar 2023 11:48:17 +0800 Subject: [PATCH 5/7] add dubbo service full source taint range --- .../handler/hookpoint/controller/impl/DubboImpl.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/controller/impl/DubboImpl.java b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/controller/impl/DubboImpl.java index feb048958..a594e7fab 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/controller/impl/DubboImpl.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/controller/impl/DubboImpl.java @@ -6,6 +6,7 @@ import io.dongtai.iast.core.handler.hookpoint.models.MethodEvent; import io.dongtai.iast.core.handler.hookpoint.models.policy.SourceNode; import io.dongtai.iast.core.handler.hookpoint.models.policy.TaintPosition; +import io.dongtai.iast.core.handler.hookpoint.models.taint.range.*; import io.dongtai.iast.core.utils.StackUtils; import io.dongtai.iast.core.utils.TaintPoolUtils; import io.dongtai.log.DongTaiLog; @@ -68,9 +69,7 @@ public static void collectDubboRequestSource(Object handler, Object invocation, tgt.add(new TaintPosition("P1")); SourceNode sourceNode = new SourceNode(src, tgt, null); - if (arguments != null && arguments.length > 0) { - TaintPoolUtils.trackObject(event, sourceNode, arguments, 0); - } + TaintPoolUtils.trackObject(event, sourceNode, arguments, 0); Map sHeaders = new HashMap(); if (headers != null) { @@ -100,6 +99,13 @@ public static void collectDubboRequestSource(Object handler, Object invocation, event.setObjectValue(handler, false); event.setTaintPositions(sourceNode.getSources(), sourceNode.getTargets()); + // for display taint range (full arguments value) + String fv = event.parameterValues.get(0).getValue(); + int hash = System.identityHashCode(fv); + int len = TaintRangesBuilder.getLength(fv); + TaintRanges tr = new TaintRanges(new TaintRange(0, len)); + event.targetRanges.add(0, new MethodEvent.MethodEventTargetRange(hash, tr)); + requestMeta.put("headers", sHeaders); JSONArray arr = new JSONArray(); for (Object arg : arguments) { From 69853f2d6d1c4e9659037a1be4f5df591b02a943 Mon Sep 17 00:00:00 2001 From: lostsnow Date: Wed, 8 Mar 2023 15:07:23 +0800 Subject: [PATCH 6/7] add xray headers --- .../hookpoint/controller/impl/HttpImpl.java | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/controller/impl/HttpImpl.java b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/controller/impl/HttpImpl.java index 7152eeb7d..fe9cd93d4 100644 --- a/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/controller/impl/HttpImpl.java +++ b/dongtai-core/src/main/java/io/dongtai/iast/core/handler/hookpoint/controller/impl/HttpImpl.java @@ -83,13 +83,21 @@ public static void solveHttpRequest(Object obj, Object req, Object resp, Map) ConfigBuilder.getInstance() .getConfig(ConfigKey.ENABLE_VERSION_HEADER)).get(); - if (enableVersionHeader) { - String versionHeaderKey = ((Config) ConfigBuilder.getInstance() - .getConfig(ConfigKey.VERSION_HEADER_KEY)).get(); + String xrayHeader = ((Map) requestMeta.get("headers")).get("Xray"); + if (enableVersionHeader || xrayHeader != null) { Method setHeaderMethod = ReflectUtils.getDeclaredMethodFromSuperClass(resp.getClass(), "setHeader", new Class[]{String.class, String.class}); if (setHeaderMethod != null) { - setHeaderMethod.invoke(resp, versionHeaderKey, AgentConstant.VERSION_VALUE); + if (enableVersionHeader) { + String versionHeaderKey = ((Config) ConfigBuilder.getInstance() + .getConfig(ConfigKey.VERSION_HEADER_KEY)).get(); + setHeaderMethod.invoke(resp, versionHeaderKey, AgentConstant.VERSION_VALUE); + } + if (xrayHeader != null) { + String reqId = String.valueOf(EngineManager.getAgentId()) + "." + + UUID.randomUUID().toString().replaceAll("-", ""); + setHeaderMethod.invoke(resp, "dt-request-id", reqId); + } } } } catch (Throwable ignore) { @@ -141,6 +149,8 @@ public static Map parseRequestHeaders(Object req, Enumeration String val = (String) getHeaderMethod.invoke(req, key); if ("content-type".equalsIgnoreCase(key)) { key = "Content-Type"; + } else if ("xray".equalsIgnoreCase(key)) { + key = "Xray"; } headers.put(key, val); } catch (Throwable ignore) { From eef4d8f15b444eecfffade3a5ef2d4837276d3ca Mon Sep 17 00:00:00 2001 From: lostsnow Date: Fri, 10 Mar 2023 18:30:05 +0800 Subject: [PATCH 7/7] bump version to 1.9.0-beta1 --- .github/workflows/code-check.yml | 8 ++++++-- .github/workflows/codeql-analysis.yml | 8 ++++++-- .../io/dongtai/iast/common/constants/AgentConstant.java | 2 +- pom.xml | 2 +- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/.github/workflows/code-check.yml b/.github/workflows/code-check.yml index a25172bdd..a30922207 100644 --- a/.github/workflows/code-check.yml +++ b/.github/workflows/code-check.yml @@ -5,9 +5,13 @@ name: Build Agent and Upload To OSS on: push: - branches: [ beta ] + branches: + - main + - beta pull_request: - branches: [ beta ] + branches: + - main + - beta paths-ignore: - '.github/**' - 'changes/**' diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 3b5f99576..a32cb192e 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -13,7 +13,9 @@ name: "CodeQL" on: push: - branches: [ main ] + branches: + - main + - beta paths-ignore: - '.github/**' - 'changes/**' @@ -24,7 +26,9 @@ on: - 'LICENSE' - '.gitignore' pull_request: - branches: [ main ] + branches: + - main + - beta paths-ignore: - '.github/**' - 'changes/**' diff --git a/dongtai-common/src/main/java/io/dongtai/iast/common/constants/AgentConstant.java b/dongtai-common/src/main/java/io/dongtai/iast/common/constants/AgentConstant.java index 671719c56..799b82bb7 100644 --- a/dongtai-common/src/main/java/io/dongtai/iast/common/constants/AgentConstant.java +++ b/dongtai-common/src/main/java/io/dongtai/iast/common/constants/AgentConstant.java @@ -1,7 +1,7 @@ package io.dongtai.iast.common.constants; public class AgentConstant { - public static final String VERSION_VALUE = "v1.8.2-beta3"; + public static final String VERSION_VALUE = "v1.9.0-beta1"; public static final String LANGUAGE = "JAVA"; public static final String THREAD_NAME_PREFIX = "DongTai-IAST-"; public static final String THREAD_NAME_PREFIX_CORE = "DongTai-IAST-Core-"; diff --git a/pom.xml b/pom.xml index a838bee28..57579a3ed 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 - 1.8.2-beta3 + 1.9.0-beta1 UTF-8 io.dongtai.iast.thirdparty