JavaSec-RCE
简介
RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection)
代码注入
1.漏洞场景:Groovy代码注入
Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,常用于脚本开发和自动化任务Groovy代码注入漏洞通常是由于未对用户输入进行适当的验证和过滤,导致恶意输入被直接执行为 Groovy脚本的一部分
public R vulGroovy(String payload) {try {GroovyShell shell = new GroovyShell();Object result = shell.evaluate(payload); if (result instanceof Process) {Process process = (Process) result;String output = getProcessOutput(process);return R.ok("[+] Groovy代码执行,结果:" + output);} else {return R.ok("[+] Groovy代码执行,结果:" + result.toString());}} catch (Exception e) {return R.error(e.getMessage());}
}
private String getProcessOutput(Process process) {StringBuilder output = new StringBuilder();try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {String line;while ((line = reader.readLine()) != null) {output.append(line).append("\n");}} catch (Exception e) {return "读取输出失败: " + e.getMessage();}return output.toString();
}
2.安全场景:Groovy脚本白名单
public R safeGroovy(String payload) {List<String> trustedScripts = Arrays.asList("\"id\".execute()","\"ls\".execute()","\"whoami\".execute()");if (!isTrustedScript(payload, trustedScripts)) {return R.error("非法的脚本输入!");}try {GroovyShell shell = new GroovyShell();Object result = shell.evaluate(payload); if (result instanceof Process) {Process process = (Process) result;String output = getProcessOutput(process);return R.ok("[+] 执行受信任的脚本,结果:" + output);} else {return R.ok("[+] 执行受信任的脚本,结果:" + result.toString());}} catch (Exception e) {return R.error(e.getMessage());}
}
private boolean isTrustedScript(String script, List<String> trustedScripts) {return trustedScripts.contains(script);
}
命令注入
1.漏洞场景:ProcessBuilder
public R vul1(String payload) throws IOException {String[] command = {"sh", "-c",payload};ProcessBuilder pb = new ProcessBuilder(command);pb.redirectErrorStream(true);Process process = pb.start();InputStream inputStream = process.getInputStream();BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));String line;StringBuilder output = new StringBuilder();while ((line = reader.readLine()) != null) {output.append(line).append("\n");}return R.ok(output.toString());
2.漏洞场景:Runtime.getRuntime().exec()
代码审计SINK点:1、ProcessBuilder2、Runtime.exec()3、反射调用 ProcessImpl.start
public R vul2(String payload) throws IOException {StringBuilder sb = new StringBuilder();String line;Process proc = Runtime.getRuntime().exec(payload);InputStream inputStream = proc.getInputStream();InputStreamReader isr = new InputStreamReader(inputStream);BufferedReader br = new BufferedReader(isr);while ((line = br.readLine()) != null) {sb.append(line);}return R.ok(sb.toString());
}
3.漏洞场景:ProcessImpl
安全编码规范:1、限制执行权限:避免使用Runtime、ProcessBuilder等函数,即使使用这类函数也应确保执行命令的进程具有最小权限,避免提升到更高的权限级别。2、避免直接拼接命令字符串:尽可能使用专门的API或库来处理系统任务,避免直接构建和执行命令字符串3、输入验证:对所有用户输入进行严格验证,确保符合预期格式,建立白名单机制,仅允许合法的输入和命令类型
public R vul3(String payload) throws Exception {// 获取 ProcessImpl 类对象Class<?> clazz = Class.forName("java.lang.ProcessImpl");// 获取 start 方法Method method = clazz.getDeclaredMethod("start", String[].class, Map.class, String.class, ProcessBuilder.Redirect[].class, boolean.class);method.setAccessible(true);Process process = (Process) method.invoke(null, new String[]{payload}, null, null, null, false);try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {StringBuilder output = new StringBuilder();String line;while ((line = reader.readLine()) != null) {output.append(line).append("\n");}return R.ok(output.toString());}
}
4.安全场景:白名单限制
安全代码
// 验证命令是否在允许的列表中
if (!ALLOWED_COMMANDS.contains(payload)) {return R.error("不允许执行该命令!");
}// 可执行命令白名单
private static final List<String> ALLOWED_COMMANDS = Arrays.asList("ls", "date");