Skip to content

Commit fbb25f8

Browse files
committed
Add support for arrayCmd methods and more smoke tests
1 parent 766e088 commit fbb25f8

File tree

7 files changed

+80
-12
lines changed

7 files changed

+80
-12
lines changed

dd-java-agent/appsec/src/main/java/com/datadog/appsec/gateway/GatewayBridge.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ private Flow<Void> onNetworkConnection(RequestContext ctx_, String url) {
260260
}
261261
}
262262

263-
private Flow<Void> onShellCmd(RequestContext ctx_, String command) {
263+
private Flow<Void> onShellCmd(RequestContext ctx_, Object command) {
264264
AppSecRequestContext ctx = ctx_.getData(RequestContextSlot.APPSEC);
265265
if (ctx == null) {
266266
return NoopFlow.INSTANCE;

dd-java-agent/instrumentation/java-lang/src/main/java/datadog/trace/instrumentation/java/lang/ShellCmdRaspHelper.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,19 @@ private ShellCmdRaspHelper() {
2626
}
2727

2828
public void beforeShellCmd(@Nonnull final String[] cmdArray) {
29-
// TODO
29+
shellCmd(cmdArray);
3030
}
3131

3232
public void beforeShellCmd(@Nonnull final String cmd) {
33+
shellCmd(cmd);
34+
}
35+
36+
private void shellCmd(Object cmd) {
3337
if (!Config.get().isAppSecRaspEnabled()) {
3438
return;
3539
}
3640
try {
37-
final BiFunction<RequestContext, String, Flow<Void>> shellCmdCallback =
41+
final BiFunction<RequestContext, Object, Flow<Void>> shellCmdCallback =
3842
AgentTracer.get()
3943
.getCallbackProvider(RequestContextSlot.APPSEC)
4044
.getCallback(EVENTS.shellCmd());

dd-java-agent/instrumentation/java-lang/src/test/groovy/datadog/trace/instrumentation/java/lang/ShellCmdRaspHelperForkedTest.groovy

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ class ShellCmdRaspHelperForkedTest extends AgentTestRunner {
4646

4747
@Override
4848
protected void configurePreAgent() {
49-
injectSysConfig(IastConfig.IAST_ENABLED, 'true')
5049
injectSysConfig(AppSecConfig.APPSEC_ENABLED, 'true')
5150
injectSysConfig(AppSecConfig.APPSEC_RASP_ENABLED, 'true')
5251
}
@@ -67,7 +66,8 @@ class ShellCmdRaspHelperForkedTest extends AgentTestRunner {
6766
1 * listener.apply(reqCtx, expected) >> flow
6867

6968
where:
70-
args | expected
71-
['&lt;!--#exec%20cmd=&quot;/bin/cat%20/etc/passwd&quot;--&gt;'] | '&lt;!--#exec%20cmd=&quot;/bin/cat%20/etc/passwd&quot;--&gt;'
69+
args | expected
70+
['cat etc/password'] | 'cat etc/password'
71+
[['cat etc/password', 'cat etc/password'] as String[]] | ['cat etc/password', 'cat etc/password']
7272
}
7373
}

dd-smoke-tests/appsec/springboot/src/main/java/datadog/smoketest/appsec/springboot/controller/WebController.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,12 +159,46 @@ public ResponseEntity<String> session(final HttpServletRequest request) {
159159
return new ResponseEntity<>(session.getId(), HttpStatus.OK);
160160
}
161161

162+
@PostMapping("/shi/arrayCmd")
163+
public String shiArrayCmd(@RequestParam("cmd") String[] arrayCmd) {
164+
withProcess(() -> Runtime.getRuntime().exec(arrayCmd));
165+
return "EXECUTED";
166+
}
167+
162168
@PostMapping("/shi/cmd")
163169
public String shiCmd(@RequestParam("cmd") String cmd) {
164170
withProcess(() -> Runtime.getRuntime().exec(cmd));
165171
return "EXECUTED";
166172
}
167173

174+
@PostMapping("/shi/arrayCmdWithParams")
175+
public String shiArrayCmdWithParams(
176+
@RequestParam("cmd") String[] arrayCmd, @RequestParam("params") String[] params) {
177+
withProcess(() -> Runtime.getRuntime().exec(arrayCmd, params));
178+
return "EXECUTED";
179+
}
180+
181+
@PostMapping("/shi/cmdWithParams")
182+
public String shiCmdWithParams(
183+
@RequestParam("cmd") String cmd, @RequestParam("params") String[] params) {
184+
withProcess(() -> Runtime.getRuntime().exec(cmd, params));
185+
return "EXECUTED";
186+
}
187+
188+
@PostMapping("/shi/arrayCmdWithParamsAndFile")
189+
public String shiArrayCmdWithParamsAndFile(
190+
@RequestParam("cmd") String[] arrayCmd, @RequestParam("params") String[] params) {
191+
withProcess(() -> Runtime.getRuntime().exec(arrayCmd, params, new File("")));
192+
return "EXECUTED";
193+
}
194+
195+
@PostMapping("/shi/cmdParamsAndFile")
196+
public String shiCmdParamsAndFile(
197+
@RequestParam("cmd") String cmd, @RequestParam("params") String[] params) {
198+
withProcess(() -> Runtime.getRuntime().exec(cmd, params, new File("")));
199+
return "EXECUTED";
200+
}
201+
168202
private void withProcess(final Operation<Process> op) {
169203
Process process = null;
170204
try {

dd-smoke-tests/appsec/springboot/src/test/groovy/datadog/smoketest/appsec/SpringBootSmokeTest.groovy

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -531,8 +531,17 @@ class SpringBootSmokeTest extends AbstractAppSecServerSmokeTest {
531531

532532
void 'rasp blocks on SHI'() {
533533
when:
534-
String url = "http://localhost:${httpPort}/shi/cmd"
535-
final body = new FormBody.Builder().add("cmd", "cat etc/password").build()
534+
String url = "http://localhost:${httpPort}/shi/"+endpoint
535+
def formBuilder = new FormBody.Builder()
536+
for (s in cmd) {
537+
formBuilder.add("cmd", s)
538+
}
539+
if (params != null) {
540+
for (s in params) {
541+
formBuilder.add("params", s)
542+
}
543+
}
544+
final body = formBuilder.build()
536545
def request = new Request.Builder()
537546
.url(url)
538547
.post(body)
@@ -561,6 +570,15 @@ class SpringBootSmokeTest extends AbstractAppSecServerSmokeTest {
561570
}
562571
}
563572
assert trigger != null, 'test trigger not found'
573+
574+
where:
575+
endpoint | cmd | params
576+
'cmd' | ['cat etc/password'] | null
577+
'arrayCmd' | ['cat etc/password', 'cat etc/password'] | null
578+
'cmdWithParams' | ['cat etc/password'] | ['param']
579+
'arrayCmdWithParams' | ['cat etc/password', 'cat etc/password'] | ['param']
580+
'cmdParamsAndFile' | ['cat etc/password'] | ['param']
581+
'arrayCmdWithParamsAndFile' | ['cat etc/password', 'cat etc/password'] | ['param']
564582
}
565583

566584
}

internal-api/src/main/java/datadog/trace/api/gateway/Events.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -313,10 +313,9 @@ public EventType<TriFunction<RequestContext, UserIdCollectionMode, String, Flow<
313313
@SuppressWarnings("rawtypes")
314314
private static final EventType SHELL_CMD = new ET<>("shell.cmd", SHELL_CDM_ID);
315315

316-
/** A I/O network URL */
317316
@SuppressWarnings("unchecked")
318-
public EventType<BiFunction<RequestContext, String, Flow<Void>>> shellCmd() {
319-
return (EventType<BiFunction<RequestContext, String, Flow<Void>>>) SHELL_CMD;
317+
public EventType<BiFunction<RequestContext, Object, Flow<Void>>> shellCmd() {
318+
return (EventType<BiFunction<RequestContext, Object, Flow<Void>>>) SHELL_CMD;
320319
}
321320

322321
static final int MAX_EVENTS = nextId.get();

internal-api/src/main/java/datadog/trace/api/gateway/InstrumentationGateway.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,6 @@ public Flow<Void> apply(RequestContext ctx, String arg) {
419419
case DATABASE_SQL_QUERY_ID:
420420
case NETWORK_CONNECTION_ID:
421421
case FILE_LOADED_ID:
422-
case SHELL_CDM_ID:
423422
return (C)
424423
new BiFunction<RequestContext, String, Flow<Void>>() {
425424
@Override
@@ -433,6 +432,20 @@ public Flow<Void> apply(RequestContext ctx, String arg) {
433432
}
434433
}
435434
};
435+
case SHELL_CDM_ID:
436+
return (C)
437+
new BiFunction<RequestContext, Object, Flow<Void>>() {
438+
@Override
439+
public Flow<Void> apply(RequestContext ctx, Object arg) {
440+
try {
441+
return ((BiFunction<RequestContext, Object, Flow<Void>>) callback)
442+
.apply(ctx, arg);
443+
} catch (Throwable t) {
444+
log.warn("Callback for {} threw.", eventType, t);
445+
return Flow.ResultFlow.empty();
446+
}
447+
}
448+
};
436449
default:
437450
log.warn("Unwrapped callback for {}", eventType);
438451
return callback;

0 commit comments

Comments
 (0)