当前位置: 首页 > 技术干货 > Solon框架模板漏洞深度剖析与修复实战

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

发表于:2025-06-05 15:54 作者: 标准云 阅读数(78人)

前言

分析发现 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 编码虽然可以绕过检测,但是实际处理时,找不到文件所在的位置,再加上并不是从根目录开始读取文件的,最前面还存在目录限制,所以这样一来就无法利用这个漏洞了。

本课程最终解释权归蚁景网安学院

本页面信息仅供参考,请扫码咨询客服了解本课程最新内容和活动

🎈网安学院推荐课程: 渗透测试工程师特训班 Web安全工程师特训班 Python网络安全实战班 应急响应安全工程师特训班
  CTF-Reverse实战技能特训班 CTF-WEB实战技能特训班 CTF-PWN实战技能特训班 CTF-MISC实战技能特训班   SRC赏金猎人大师班 HVV大师课