Java中使用getRuntime().exec()进行命令注入无法正常工作
问题分析与解决
核心问题1:URL类的解析会破坏注入字符串
当你把带分号的字符串传给URL构造器时,URL类会按URL规范解析内容:分号会被识别为URL的路径/参数分隔符,而非命令行分隔符;空格这类特殊字符会被编码成%20。最终toExternalForm()返回的字符串会变成类似https://google.com;/usr/bin/touch%20pizza.txt的格式,bash无法识别编码后的空格和被URL规范处理的分号,自然无法执行注入命令。
核心问题2:Runtime.exec调用bash的方式错误
直接执行/bin/bash 字符串时,bash会把整个字符串当作程序名而非命令内容。正确的做法是使用bash -c参数来指定要执行的命令字符串。
修复后的代码示例
如果只是练习命令注入,无需通过URL类处理字符串(它会破坏注入语法),直接构造命令并正确调用exec即可:
class Solution { public static void main(String args[]) { try { // 直接构造包含注入逻辑的命令字符串 String injectCmd = "curl https://google.com;/usr/bin/touch pizza.txt"; // 用bash -c执行命令,用数组形式避免参数拆分问题 Runtime.getRuntime().exec(new String[]{"/bin/bash", "-c", injectCmd}); } catch (Exception e) { System.out.println(e); } } }
如果必须模拟真实场景中基于URL参数的注入,需要先从URL中提取注入部分再处理:
import java.net.URL; class Solution { public static void main(String args[]) { URL url = null; try { url = new URL("https://google.com;/usr/bin/touch pizza.txt"); // 提取URL中包含注入命令的部分 String injectPart = url.getPath().substring(1); // 去掉开头的/ // 构造完整执行命令 String fullCmd = "curl " + url + ";" + injectPart; Runtime.getRuntime().exec(new String[]{"/bin/bash", "-c", fullCmd}); } catch (Exception e) { System.out.println(e); } } }
关键注意事项
- 优先使用
Runtime.exec(String[])而非字符串拼接,避免命令参数被错误拆分。 - 若要保留注入语法,不要让URL类修改你的命令字符串,或解析后正确提取注入逻辑部分。
- 执行文件操作时,确保程序拥有目标目录的写入权限。
内容的提问来源于stack exchange,提问作者veryveryconfus3d
相关产品推荐
相关产品推荐

