-
Notifications
You must be signed in to change notification settings - Fork 292
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Exploit prevention for Shell Injection / Command Injection (#7615)
Added support for Command Injection (CMDI) exploit prevention: Reused existing instrumentation of java.lang.ProcessImpl. Added support for Shell Injection (SHI) exploit prevention: Instrumented java.lang.Runtime#exec(String, String[], File) for detection. Leveraged SHI heuristics as a workaround for cases where the command is a single String, given that WAF heuristics for CMDI only support String[]. Enhanced RASP metrics mechanism: Introduced a new rule_variant tag to metrics. For CMDI: exec. For SHI: shell. Both variants are categorized under the ruletype as command_injection.
- Loading branch information
Showing
22 changed files
with
872 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 20 additions & 0 deletions
20
...a-lang/src/main/java/datadog/trace/instrumentation/java/lang/RuntimeExecStringAdvice.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package datadog.trace.instrumentation.java.lang; | ||
|
||
import datadog.trace.bootstrap.instrumentation.api.java.lang.ProcessImplInstrumentationHelpers; | ||
import java.io.IOException; | ||
import net.bytebuddy.asm.Advice; | ||
|
||
class RuntimeExecStringAdvice { | ||
@Advice.OnMethodEnter(suppress = Throwable.class) | ||
public static void beforeExec(@Advice.Argument(0) final String command) throws IOException { | ||
if (command == null) { | ||
return; | ||
} | ||
ProcessImplInstrumentationHelpers.shiRaspCheck(command); | ||
} | ||
|
||
@Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class) | ||
public static void afterExec() { | ||
ProcessImplInstrumentationHelpers.resetCheckShi(); | ||
} | ||
} |
37 changes: 37 additions & 0 deletions
37
...va-lang/src/main/java/datadog/trace/instrumentation/java/lang/RuntimeInstrumentation.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package datadog.trace.instrumentation.java.lang; | ||
|
||
import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named; | ||
import static net.bytebuddy.matcher.ElementMatchers.takesArguments; | ||
|
||
import com.google.auto.service.AutoService; | ||
import datadog.trace.agent.tooling.Instrumenter; | ||
import datadog.trace.agent.tooling.InstrumenterModule; | ||
import datadog.trace.api.Platform; | ||
import java.io.File; | ||
|
||
@AutoService(InstrumenterModule.class) | ||
public class RuntimeInstrumentation extends InstrumenterModule.AppSec | ||
implements Instrumenter.ForSingleType, Instrumenter.ForBootstrap { | ||
|
||
public RuntimeInstrumentation() { | ||
super("java-lang-appsec"); | ||
} | ||
|
||
@Override | ||
protected boolean defaultEnabled() { | ||
return super.defaultEnabled() | ||
&& !Platform.isNativeImageBuilder(); // not applicable in native-image | ||
} | ||
|
||
@Override | ||
public String instrumentedType() { | ||
return "java.lang.Runtime"; | ||
} | ||
|
||
@Override | ||
public void methodAdvice(MethodTransformer transformer) { | ||
transformer.applyAdvice( | ||
named("exec").and(takesArguments(String.class, String[].class, File.class)), | ||
packageName + ".RuntimeExecStringAdvice"); | ||
} | ||
} |
68 changes: 68 additions & 0 deletions
68
...og/trace/instrumentation/java/lang/ProcessImplInstrumentationExecCmdRaspForkedTest.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package datadog.trace.instrumentation.java.lang | ||
|
||
import datadog.trace.agent.test.AgentTestRunner | ||
import datadog.trace.api.config.AppSecConfig | ||
import datadog.trace.api.gateway.CallbackProvider | ||
import datadog.trace.api.gateway.Flow | ||
import datadog.trace.api.gateway.RequestContext | ||
import datadog.trace.api.gateway.RequestContextSlot | ||
import datadog.trace.api.internal.TraceSegment | ||
import datadog.trace.bootstrap.instrumentation.api.AgentSpan | ||
import datadog.trace.bootstrap.instrumentation.api.AgentTracer | ||
import datadog.trace.bootstrap.instrumentation.api.java.lang.ProcessImplInstrumentationHelpers | ||
import spock.lang.Shared | ||
|
||
import java.util.function.BiFunction | ||
|
||
import static datadog.trace.api.gateway.Events.EVENTS | ||
|
||
class ProcessImplInstrumentationExecCmdRaspForkedTest extends AgentTestRunner { | ||
|
||
@Shared | ||
protected static final ORIGINAL_TRACER = AgentTracer.get() | ||
|
||
protected traceSegment | ||
protected reqCtx | ||
protected span | ||
protected tracer | ||
|
||
void setup() { | ||
traceSegment = Stub(TraceSegment) | ||
reqCtx = Stub(RequestContext) { | ||
getTraceSegment() >> traceSegment | ||
} | ||
span = Stub(AgentSpan) { | ||
getRequestContext() >> reqCtx | ||
} | ||
tracer = Stub(AgentTracer.TracerAPI) { | ||
activeSpan() >> span | ||
} | ||
AgentTracer.forceRegister(tracer) | ||
} | ||
|
||
void cleanup() { | ||
AgentTracer.forceRegister(ORIGINAL_TRACER) | ||
} | ||
|
||
@Override | ||
protected void configurePreAgent() { | ||
injectSysConfig(AppSecConfig.APPSEC_ENABLED, 'true') | ||
injectSysConfig(AppSecConfig.APPSEC_RASP_ENABLED, 'true') | ||
} | ||
|
||
void 'test cmdiRaspCheck'() { | ||
|
||
setup: | ||
final callbackProvider = Mock(CallbackProvider) | ||
final listener = Mock(BiFunction) | ||
final flow = Mock(Flow) | ||
tracer.getCallbackProvider(RequestContextSlot.APPSEC) >> callbackProvider | ||
|
||
when: | ||
ProcessImplInstrumentationHelpers.cmdiRaspCheck(['/bin/../usr/bin/reboot', '-f'] as String[]) | ||
|
||
then: | ||
1 * callbackProvider.getCallback(EVENTS.execCmd()) >> listener | ||
1 * listener.apply(reqCtx, ['/bin/../usr/bin/reboot', '-f']) >> flow | ||
} | ||
} |
Oops, something went wrong.