Checkmarx命令行注入修复咨询:ProcessBuilder代码仍存漏洞
修复命令行注入漏洞的方案
原代码的核心问题
- 通过shell执行命令:使用
/bin/sh -c启动进程会让shell解析命令字符串,即便做了字符过滤,也存在注入风险;而且参数传递逻辑错误,-c后的第一个参数会被shell当作完整命令执行,后续参数仅作为$1、$2等变量,若脚本中不当使用这些变量,仍可能触发注入。 - 过滤方式不安全:仅用
replaceAll("[^A-Za-z0-9]", "")做黑名单过滤,无法覆盖所有注入场景,且如果允许的参数有明确范围,黑名单远不如白名单可靠。
修复后的代码
public String executeSystemCommand_WithParameters(HttpServletRequest request) throws ServletException, IOException { String commandResult = ""; String userInput = request.getParameter("Command"); // 1. 严格白名单验证:仅允许符合预期的输入(示例:假设只允许特定的合法参数值) if (!isValidUserInput(userInput)) { throw new IllegalArgumentException("Invalid input parameter"); } try { // 2. 直接调用Python解释器,绕过shell,避免命令解析风险 // 替换为你的Python解释器路径(如/usr/bin/python3)和脚本路径 ProcessBuilder builder = new ProcessBuilder("/usr/bin/python3", PROGRAM_NAME, userInput); Map<String, String> environ = builder.environment(); setEnvironmentVars(environ); Process subProc = builder.start(); // 读取输出(用StringBuilder提升性能) StringBuilder sb = new StringBuilder(); BufferedReader irProcOutput = new BufferedReader(new InputStreamReader(subProc.getInputStream())); String line; while ((line = irProcOutput.readLine()) != null) { sb.append(line); } irProcOutput.close(); // 等待进程结束并检查退出码 int exitCode = subProc.waitFor(); if (exitCode != 0) { // 处理错误输出 BufferedReader errorReader = new BufferedReader(new InputStreamReader(subProc.getErrorStream())); StringBuilder errorSb = new StringBuilder(); String errorLine; while ((errorLine = errorReader.readLine()) != null) { errorSb.append(errorLine); } errorReader.close(); throw new IOException("Process exited with code " + exitCode + ": " + errorSb.toString()); } commandResult = sb.toString(); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); handleExceptions(ex); } catch (Exception ex) { handleExceptions(ex); } return commandResult; } // 自定义白名单验证方法:根据实际业务需求定义合法输入规则 private boolean isValidUserInput(String input) { // 示例:仅允许长度在1-20之间的字母数字组合,或者特定的命令参数 if (input == null || input.isEmpty()) { return false; } // 替换为你的业务允许的正则,比如只允许特定的操作指令 return input.matches("[A-Za-z0-9]{1,20}"); }
关键修复点
- 绕过shell执行:直接调用Python解释器和目标脚本,让ProcessBuilder将每个参数作为独立的命令行参数传递,避免shell对命令字符串的解析,从根源上消除命令注入风险。
- 白名单验证:替换黑名单过滤为严格的白名单校验,只允许符合业务预期的输入,拒绝所有非法内容。
- 完善进程处理:添加进程退出码检查和错误输出读取,便于排查问题,同时用
StringBuilder替代字符串拼接提升性能。
内容的提问来源于stack exchange,提问作者Gaurav Wadhone
相关产品推荐
相关产品推荐

