java-sec-code中命令注入

java-sec-code中命令注入
不安全的写法(由于我这里使用的是idea搭建的环境,原本命令执行的sh -c 无法运行,后续的输出也会产生乱码,修改部分代码,以便能更好的显示出效果,linux下使用docker木有问题)

//需要导入的库文件
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@GetMapping("/codeinject")
public String codeInject(String filepath) throws IOException {
    String[] cmdList = new String[]{"cmd.exe", "/c", "dir", filepath};
    ProcessBuilder builder = new ProcessBuilder(cmdList);
    builder.environment().put("LC_ALL", "GBK");
    builder.redirectErrorStream(true);
    Process process = builder.start();
    //return WebUtils.convertStreamToString(process.getInputStream());
    try (InputStream inputStream = process.getInputStream();
         BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "GBK"))) {
        String line;
        StringBuilder output = new StringBuilder();
        while ((line = reader.readLine()) != null) {
            output.append(line).append("\n");
        }
        return output.toString();
    }
}

当用户访问codeinject路由时,服务端会获取filepath参数内容并进行拼接,创建外部进程执行拼接后的命令,并将输出字符转换为字符串进行输出,由于程序并未对用户输入进行过滤,导致命令注入的产生。

复现 这里filepath后面的参数需要url编码,使用hackbar编码即可
windows下

http://127.0.0.1:8080/codeinject?filepath=D%3A%5Calibaba%26%26ipconfig

java-sec-code中命令注入_第1张图片
linux下

http://192.168.2.5:8080/codeinject?filepath=/tmp;cat /etc/passwd

java-sec-code中命令注入_第2张图片
host位置(个人认为这个位置不会产生命令注入,请求包中host用来指定请求的目标服务器,如果修改为127.0.0.1:8080|ipconfig或者127.0.0.1:8080&ipconfig等形式,连正常的http连接都建立不了,更不要说后续的漏洞利用了,这里只是个人的粗鄙之见,还希望大佬不吝赐教,至于别的博文提供的192.168.2.5;id && pwd linux和windows下均无法复现)
代码

@GetMapping("/codeinject/host")
public String codeInjectHost(HttpServletRequest request) throws IOException {

    String host = request.getHeader("host");
    logger.info(host);
    String[] cmdList = new String[]{"cmd.exe", "/c", "curl", host};
    ProcessBuilder builder = new ProcessBuilder(cmdList);
    builder.redirectErrorStream(true);
    Process process = builder.start();
    try (InputStream inputStream = process.getInputStream();
         BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "GBK"))) {
        String line;
        StringBuilder output = new StringBuilder();
        while ((line = reader.readLine()) != null) {
            output.append(line).append("\n");
        }
        return output.toString();
    }
}

简单地说,网站获取用户请求的host的属性值,然后进行拼接,命令执行,但是由于host属性值的特殊性,host无法添加特殊字符&| ,无法利用

安全代码

@GetMapping("/codeinject/sec")
public String codeInjectSec(String filepath) throws IOException {
    String filterFilePath = SecurityUtil.cmdFilter(filepath);
    if (null == filterFilePath) {
        return "Bad boy. I got u.";
    }
    String[] cmdList = new String[]{"cmd.exe", "/c", "dir", filepath};
    ProcessBuilder builder = new ProcessBuilder(cmdList);
    builder.redirectErrorStream(true);
    Process process = builder.start();
    try (InputStream inputStream = process.getInputStream();
         BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "GBK"))) {
        String line;
        StringBuilder output = new StringBuilder();
        while ((line = reader.readLine()) != null) {
            output.append(line).append("\n");
        }
        return output.toString();
    }
}
private static final Pattern FILTER_PATTERN = Pattern.compile("^[a-zA-Z0-9_/\\.-]+$");
public static String cmdFilter(String input) {
    if (!FILTER_PATTERN.matcher(input).matches()) {
        return null;
    }

    return input;
}

这里使用正则表达式进行匹配,是否只包含字母、数字、下划线、斜杠、点或破折号,如果是,则进行命令拼接运行,否则返回Bad boy. I got u
windows下
如果为D:\ 存在冒号,反斜杠,不符合要求,会输出Bad boy. I got u
java-sec-code中命令注入_第3张图片
linux如果为/tmp只有斜杠和小写字母,符合要求,拼接运行
如果为/tmp;cat /etc/passwd 则会因为出现分号的原因输出Bad boy. I got u
如果需要在windows下查看结果 需要将正则修改为

^[a-zA-Z0-9_/\\\\.-]+$

java-sec-code中命令注入_第4张图片
java-sec-code中命令注入_第5张图片
host位置如果能够进行命令注入,希望大佬不吝赐教,评论私信均可

你可能感兴趣的:(java,开发语言)