8000 Exploit prevention for Shell Injection / Command Injection by jandro996 · Pull Request #7615 · DataDog/dd-trace-java · GitHub
[go: up one dir, main page]

Skip to content

Exploit prevention for Shell Injection / Command Injection #7615

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 25 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
bf9a508
SHI exploit prevention on one sink for java.lang.Runtime.exec(java.la…
jandro996 Sep 13, 2024
bf04013
fix spotless
jandro996 Nov 28, 2024
7043b2c
first steps to add cmdArray support (not blocking)
jandro996 Nov 29, 2024
f3bb30f
Fix known addresses
jandro996 Dec 10, 2024
8323532
Fix test
jandro996 Dec 10, 2024
663712b
Add support for arrayCmd methods and more smoke tests
jandro996 Dec 10, 2024
68f08b2
Add support for arrayCmd methods and more smoke tests
jandro996 Dec 10, 2024
3b62d1c
Add support for arrayCmd methods and more smoke tests
jandro996 Dec 10, 2024
d7226e1
Add support for ProcessBuilder
jandro996 Dec 10, 2024
b488d8a
Move to ProcessImplInstrumentation approach
jandro996 Dec 11, 2024
6d97145
Change to cmdi keeping ProcessImpl approach
jandro996 Dec 11, 2024
2c7672e
fix
jandro996 Dec 13, 2024
f3c4fe1
Add SHI
jandro996 Dec 13, 2024
996ab77
Add metrics to cmdi and shi with rule_variant tag
jandro996 Dec 13, 2024
cf855f7
Add another test
jandro996 Dec 13, 2024
92f9021
fix cmdi capability
jandro996 Dec 14, 2024
7846c74
change cmdi payloads
jandro996 Dec 16, 2024
dd3d414
Merge branch 'master' into alejandro.gonzalez/rasp-command-injection
jandro996 Dec 16, 2024
431cba1
format test
jandro996 Dec 16, 2024
650378e
fix comment
jandro996 Dec 16, 2024
c37357d
Merge branch 'master' into alejandro.gonzalez/rasp-command-injection
jandro996 Dec 16, 2024
5615a0a
change Runtime instrumentation to Appsec
jandro996 Dec 16, 2024
f384a09
Merge branch 'master' into alejandro.gonzalez/rasp-command-injection
jandro996 Dec 17, 2024
a2bc8f8
Merge branch 'master' into alejandro.gonzalez/rasp-command-injection
jandro996 Dec 18, 2024
15ba143
Merge branch 'master' into alejandro.gonzalez/rasp-command-injection
jandro996 Dec 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add support for arrayCmd methods and more smoke tests
  • Loading branch information
jandro996 committed Dec 14, 2024
commit 663712b38eb14d3dc0a17562c6f58012cc77f982
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ private Flow<Void> onNetworkConnection(RequestContext ctx_, String url) {
}
}

private Flow<Void> onShellCmd(RequestContext ctx_, String command) {
private Flow<Void> onShellCmd(RequestContext ctx_, Object command) {
AppSecRequestContext ctx = ctx_.getData(Req 8000 uestContextSlot.APPSEC);
if (ctx == null) {
return NoopFlow.INSTANCE;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,19 @@ private ShellCmdRaspHelper() {
}

public void beforeShellCmd(@Nonnull final String[] cmdArray) {
// TODO
shellCmd(cmdArray);
}

public void beforeShellCmd(@Nonnull final String cmd) {
shellCmd(cmd);
}

private void shellCmd(Object cmd) {
if (!Config.get().isAppSecRaspEnabled()) {
return;
}
try {
final BiFunction<RequestContext, String, Flow<Void>> shellCmdCallback =
final BiFunction<RequestContext, Object, Flow<Void>> shellCmdCallback =
AgentTracer.get()
.getCallbackProvider(RequestContextSlot.APPSEC)
.getCallback(EVENTS.shellCmd());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ class ShellCmdRaspHelperForkedTest extends AgentTestRunner {

@Override
protected void configurePreAgent() {
injectSysConfig(IastConfig.IAST_ENABLED, 'true')
injectSysConfig(AppSecConfig.APPSEC_ENABLED, 'true')
injectSysConfig(AppSecConfig.APPSEC_RASP_ENABLED, 'true')
}
Expand All @@ -67,7 +66,8 @@ class ShellCmdRaspHelperForkedTest extends AgentTestRunner {
1 * listener.apply(reqCtx, expected) >> flow

where:
args | expected
['&lt;!--#exec%20cmd=&quot;/bin/cat%20/etc/passwd&quot;--&gt;'] | '&lt;!--#exec%20cmd=&quot;/bin/cat%20/etc/passwd&quot;--&gt;'
args | expected
['cat etc/password'] | 'cat etc/password'
[['cat etc/password', 'cat etc/password'] as String[]] | ['cat etc/password', 'cat etc/password']
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,46 @@ public ResponseEntity<String> session(final HttpServletRequest request) {
return new ResponseEntity<>(session.getId(), HttpStatus.OK);
}

@PostMapping("/shi/arrayCmd")
public String shiArrayCmd(@RequestParam("cmd") String[] arrayCmd) {
withProcess(() -> Runtime.getRuntime().exec(arrayCmd));
return "EXECUTED";
}

@PostMapping("/shi/cmd")
public String shiCmd(@RequestParam("cmd") String cmd) {
withProcess(() -> Runtime.getRuntime().exec(cmd));
return "EXECUTED";
}

@PostMapping("/shi/arrayCmdWithParams")
public String shiArrayCmdWithParams(
@RequestParam("cmd") String[] arrayCmd, @RequestParam("params") String[] params) {
withProcess(() -> Runtime.getRuntime().exec(arrayCmd, params));
return "EXECUTED";
}

@PostMapping("/shi/cmdWithParams")
public String shiCmdWithParams(
@RequestParam("cmd") String cmd, @RequestParam("params") String[] params) {
withProcess(() -> Runtime.getRuntime().exec(cmd, params));
return "EXECUTED";
}

@PostMapping("/shi/arrayCmdWithParamsAndFile")
public String shiArrayCmdWithParamsAndFile(
@RequestParam("cmd") String[] arrayCmd, @RequestParam("params") String[] params) {
withProcess(() -> Runtime.getRuntime().exec(arrayCmd, params, new File("")));
return "EXECUTED";
}

@PostMapping("/shi/cmdParamsAndFile")
public String shiCmdParamsAndFile(
@RequestParam("cmd") String cmd, @RequestParam("params") String[] params) {
withProcess(() -> Runtime.getRuntime().exec(cmd, params, new File("")));
return "EXECUTED";
}

private void withProcess(final Operation<Process> op) {
Process process = null;
try {
Expand Down
67E6
Original file line number Diff line number Diff line change
Expand Up @@ -531,8 +531,17 @@ class SpringBootSmokeTest extends AbstractAppSecServerSmokeTest {

void 'rasp blocks on SHI'() {
when:
String url = "http://localhost:${httpPort}/shi/cmd"
final body = new FormBody.Builder().add("cmd", "cat etc/password").build()
String url = "http://localhost:${httpPort}/shi/"+endpoint
def formBuilder = new FormBody.Builder()
for (s in cmd) {
formBuilder.add("cmd", s)
}
if (params != null) {
for (s in params) {
formBuilder.add("params", s)
}
}
final body = formBuilder.build()
def request = new Request.Builder()
.url(url)
.post(body)
Expand Down Expand Up @@ -561,6 +570,15 @@ class SpringBootSmokeTest extends AbstractAppSecServerSmokeTest {
}
}
assert trigger != null, 'test trigger not found'

where:
endpoint | cmd | params
'cmd' | ['cat etc/password'] | null
'arrayCmd' | ['cat etc/password', 'cat etc/password'] | null
'cmdWithParams' | ['cat etc/password'] | ['param']
'arrayCmdWithParams' | ['cat etc/password', 'cat etc/password'] | ['param']
'cmdParamsAndFile' | ['cat etc/password'] | ['param']
'arrayCmdWithParamsAndFile' | ['cat etc/password', 'cat etc/password'] | ['param']
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -313,10 +313,9 @@ public EventType<TriFunction<RequestContext, UserIdCollectionMode, String, Flow<
@SuppressWarnings("rawtypes")
private static final EventType SHELL_CMD = new ET<>("shell.cmd", SHELL_CDM_ID);

/** A I/O network URL */
@SuppressWarnings("unchecked")
public EventType<BiFunction<RequestContext, String, Flow<Void>>> shellCmd() {
return (EventType<BiFunction<RequestContext, String, Flow<Void>>>) SHELL_CMD;
public EventType<BiFunction<RequestContext, Object, Flow<Void>>> shellCmd() {
return (EventType<BiFunction<RequestContext, Object, Flow<Void>>>) SHELL_CMD;
}

static final int MAX_EVENTS = nextId.get();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,6 @@ public Flow<Void> apply(RequestContext ctx, String arg) {
case DATABASE_SQL_QUERY_ID:
case NETWORK_CONNECTION_ID:
case FILE_LOADED_ID:
case SHELL_CDM_ID:
return (C)
new BiFunction<RequestContext, String, Flow<Void>>() {
@Override
Expand All @@ -433,6 +432,20 @@ public Flow<Void> apply(RequestContext ctx, String arg) {
}
}
};
case SHELL_CDM_ID:
return (C)
new BiFunction<RequestContext, Object, Flow<Void>>() {
@Override
public Flow<Void> apply(RequestContext ctx, Object arg) {
try {
return ((BiFunction<RequestContext, Object, Flow<Void>>) callback)
.apply(ctx, arg);
} catch (Throwable t) {
log.warn("Callback for {} threw.", eventType, t);
return Flow.ResultFlow.empty();
}
}
};
default:
log.warn("Unwrapped callback for {}", eventType);
return callback;
Expand Down
0