Java-Sec-Code学习1

Java-Sec-Code学习1-命令注入漏洞

Case1

url: http://127.0.0.1:8080/codeinject?filepath=/tmp;cat%20/etc/passwd
这是一个典型的命令注入payload,通过;符号即可实现命令分隔,实现多命令执行。那么该漏洞背后的对应的代码实现是什么呢?我们来探索一下:

    @GetMapping("/codeinject")
    public String codeInject(String filepath) throws IOException {

        String[] cmdList = new String[]{"sh", "-c", "ls -la " + filepath};
        ProcessBuilder builder = new ProcessBuilder(cmdList);
        builder.redirectErrorStream(true);
        Process process = builder.start();
        return WebUtils.convertStreamToString(process.getInputStream());
    }

代码非常简短,首先是Spring Boot的路由映射绑定到/codeinject路由。然后,通过接受一个String类型的filepath参数,并未经任何处理和过滤直接拼接进入到cmdList数组中了。这里的cmdList中主要是使用sh -c来实现命令调用,通过;分隔命令即可执行命令,也可以通过&符号来实现其他命令执行。
随后,通过传入cmdList创建一个ProcessBuilder类。这里的ProcessBuilder类是Java1.5引入的,用于创建和管理操作系统进程,是java.lang下的内置类。ProcessBuilder通过start方法就可用创建要给Process进程对象,这里也就导致了cmdList中的恶意语句被系统执行。最后的部分这是通过获取进程的允许结果并转为字符串返回给前端。

Case2

路由绑定在/codeinject/host中

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

        String host = request.getHeader("host");
        logger.info(host);
        String[] cmdList = new String[]{"sh", "-c", "curl " + host};
        ProcessBuilder builder = new ProcessBuilder(cmdList);
        builder.redirectErrorStream(true);
        Process process = builder.start();
        return WebUtils.convertStreamToString(process.getInputStream());
    }

这里的source点发生了变化,不是GET参数,来自HTTP header中的host参数。这里对获取到的host进行了打印,并直接拼接host参数到cmdList数组中。这里的cmdList数组也是使用sh -c来执行命令。
这里依旧是通过新建ProcessBuilder对象,并调用start方法来实现cmd命令的进程创建。同样返回执行结果的字符串形式。
payload:
在这里插入图片描述
通过修改Host头中的内容,使用127.0.0.1&whoami即可实现命令执行。

Case3

路由绑定在/codeinject/sec,这是一个修复后的案例。

    @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[]{"sh", "-c", "ls -la " + filterFilePath};
        ProcessBuilder builder = new ProcessBuilder(cmdList);
        builder.redirectErrorStream(true);
        Process process = builder.start();
        return WebUtils.convertStreamToString(process.getInputStream());
    }

这里直接获取GET参数filepath,但是在拼接到cmdList数组中前,首先通过SecurityUtil.cmdFilter的安全过滤。然后再通过ProcessBuilder对象的start方法来执行。
跟进看一下cmdFilter方法内容。

    public static String cmdFilter(String input) {
        if (!FILTER_PATTERN.matcher(input).matches()) {
            return null;
        }

        return input;
    }

在此处,通过正则匹配的方式匹配传入的内容。如果匹配成功就通过,匹配失败就返回null。

private static final Pattern FILTER_PATTERN = Pattern.compile("^[a-zA-Z0-9_/\\.-]+$");

正则表达式如上:只有数字、字母和_/\.-被允许,这才能匹配成功。
通过正则表达式限制filepath参数内容,以避免通过管道符和换行符,命令分隔符。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值