IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    Solon框架模板漏洞深度剖析与修复实战

    蚁景网安实验室发表于 2025-07-01 07:56:35
    love 0

    前言

    分析发现 Solon 框架在3.1.0版本上存在一个有意思的模板漏洞,对这个漏洞进行简单分析后,发现整个漏洞的利用链是非常有意思的。同时发现最新版的修复方式过于简单,询问 AI 后,AI 也认为修复也是不完善的安全修复,于是进行一系列的绕过尝试,最后还是没有利用成功,简单进行分享。

    环境搭建

    Solon 框架简介

    Solon 是一个轻量级的 Java 应用开发框架,类似于 Spring Boot ,但更加轻量。支持多种模板引擎,包括 Beetl、FreeMarker、Velocity 等。在模板处理方面,Solon 采用了灵活的渲染器映射机制,也是出现这个漏洞的关键原因。

    测试环境搭建

    https://solon.noear.org/start/build.do?artifact=helloworld_jdk8&project=maven&javaVer=1.8

    可以下载 solon 的项目模板 并进行修改

    修改一下 pom.xml 文件 设置 solon 的版本为 3.1.0

    将原本的视图插件 solon-view-freemarker 替换为以下的任意一种

    <dependency>
       <groupId>org.noear</groupId>
       <artifactId>solon-view-enjoy</artifactId>
    </dependency>

    <dependency>
       <groupId>org.noear</groupId>
       <artifactId>solon-view-beetl</artifactId>
    </dependency>

    <dependency>
       <groupId>org.noear</groupId>
       <artifactId>solon-view-thymeleaf</artifactId>
    </dependency>

    <dependency>
       <groupId>org.noear</groupId>
       <artifactId>solon-view-velocity</artifactId>
    </dependency>

    ‍

    在 DemoController.java 中 添加代码 并启动运行

        @Mapping("/templates")
       public ModelAndView templates(Context ctx) throws IOException {
           ModelAndView modelAndView = new ModelAndView(ctx.param("templates"));
           return modelAndView;
       }

    image

    漏洞验证与分析

    漏洞验证

    我们选用视图插件solon-view-velocity,不同的视图插件对跨目录的处理有所不同,之后会对此进行详细解释

    <dependency>
       <groupId>org.noear</groupId>
       <artifactId>solon-view-velocity</artifactId>
    </dependency>

    image

    可以看到传入的参数通过 ../ 实现了跨目录的文件读取并将内容解析到页面上

    核心调用链分析

    通过调试对这个漏洞进行分析

    遇到这种情况有一个小的 tips 我们可以通过尝试加载一个不存在的文件,这样 idea 的控制台中会输出相对详细的调用链,方便我们下断点进行调试分析。

    image

    image

    org.noear.solon.core.handle.RenderManager#render

    image

    image

    这里会根据文件后缀来选择视图插件,如果没有匹配的就选择用默认渲染器来处理

    org.noear.solon.view.velocity.VelocityRender#render

    image

    org.noear.solon.view.velocity.VelocityRender#render_mav

    image

    org.apache.velocity.runtime.RuntimeInstance#getTemplate(java.lang.String, java.lang.String)

    image

    org.apache.velocity.runtime.resource.ResourceManagerImpl#getResource

    image

    ‍

    整体流程顺下来应该是

    用户输入 → Context.param() → ModelAndView() → RenderManager.render()→ 模板引擎处理

    在模板引擎处理之前没有对模板文件的路径进行处理和限制,这样一来如果模板引擎处理的时候没有对模板文件的路径进行处理时,就会产生任意文件读取漏洞。


    我们可以尝试看看利用别的视图插件看看效果如何。

    solon-view-freemarker 为什么不可以

    image

    我们看到 freemarker 对 模板文件的路径进行了处理,不允许跨目录的访问

    org.noear.solon.view.freemarker.FreemarkerRender#render

    image

    org.noear.solon.view.freemarker.FreemarkerRender#render_mav

    image

    freemarker.template.Configuration#getTemplate(java.lang.String, java.lang.String)

    image

    freemarker.template.Configuration#getTemplate(java.lang.String, java.util.Locale, java.lang.Object, java.lang.String, boolean, boolean)

    image

    freemarker.cache.TemplateCache#getTemplate(java.lang.String, java.util.Locale, java.lang.Object, java.lang.String, boolean)

    image

    调用 name = templateNameFormat.normalizeRootBasedName(name); 来对传入的模板文件名进行处理

    freemarker.cache.TemplateNameFormat.Default020300#normalizeRootBasedName

    image

    对传入的参数进行规范化处理,以确保安全并处理路径中的特殊序列。

    漏洞修复

    org.noear.solon.core.handle.RenderManager#getViewRender

    image

    我们注意到修复方式是添加了这一部分代码

     if (mv.view().contains("../") || mv.view().contains("..\\")) {
               // '../','..\' 不安全
               throw new IllegalStateException("Invalid view path: '" + mv.view() + "'");
           }

    看起来处理方式简单粗暴,实际上是非常有效的

    用户输入 → Context.param() → ModelAndView() → RenderManager.render()→ RenderManager.getViewRender()安全检测→模板引擎处理

    在模板引擎处理之前就添加了对传入路径的检测,一次 url 编码无法绕过,两次 url 编码虽然可以绕过检测,但是实际处理时,找不到文件所在的位置,再加上并不是从根目录开始读取文件的,最前面还存在目录限制,所以这样一来就无法利用这个漏洞了。




沪ICP备19023445号-2号
友情链接