fever
fever
发布于 2024-03-08 / 14 阅读
0
0

java之ssti分析

图标
文章摘要
LIK.CC-GPT

|

springMVC视图解析

主要是Thymeleaf的ssti分析,所以有必要先了解一下springMVC架构。
在springMVC的架构下,controller的返回值如果是字符串,也就是return string。在这个过程中,Spring ViewerResolver会识别这个string,并且将它交给类似Thymeleaf这种模板去解析。Thymeleaf会识别其为模板名。这个过程有什么问题呢?实际上识别为模板名的过程,如果发现这个string是模板字符串的语句,会对其进行解析。解析语句就有可能解析恶意语句,也就是漏洞所在了。
这个过程并不需要实际上把对应的view层真正渲染出来,只要我们达到了执行模板语句的目的就够了,就像sql注入虽然会报错,导致不能正常执行,但是我们仍然成功造成了危害

Thymeleaf ssti

Thymeleaf是一款Spring官方支持的一款服务端模板引擎,一般用于Spring项目中渲染数据到View层。默认前缀:/templates/,默认后缀:.html
该模板的变量定义方式${},可以通过controller层的方法去设置模板变量的值

@GetMapping("/route")
public String index(Model model,@RequestParam String name)
  model.addAttribute("name",name); //这里设置对应模板的变量,${name}
  return "hello";//返回的字符串为hello

当这个c在return 字符串的时候,会交给Thymeleaf去识别,并解析,然后再去渲染到具体的某个模板。
当这个字符串可控或者部分可控的时候,能进行模板语句的注入。

Thymeleaf模版注入漏洞分两种场景,按照经Servlet处理后得到的viewTemplateName包含"::"和不包含"::"两种情况。
WeChat77797a60a94977bfc69af25f3c42ba24.jpg
对于着两种情况,会有不同的处理逻辑。
1、 当不包含"::"时
直接处理viewTemplateName对应的模版文件。如果模版文件中包含th:text等形式的属性且内容可控,即可通过向th:text属性值中注入SPEL表达式,经渲染后可执行该表达式。
比如

<span th:text="${T(java.lang.Runtime).getRuntime.exec('calc')}"></span>

直接注入模板语句就会进行代码执行,这里th:text是必须存在,内容才能被模板操作,类似的还有 th:fragment。

2、存在“::”的时候,是一个切面的概念,需要匹配到模板代码的正则才会解析语句。
触发绝大多数Thymeleaf模版注入漏洞的场景是这种情况。
如果符合__(.*?)__正则匹配,则取出(.*?)的数据当作表达式解析执行。
WeChat4b229c4f839790c7f2f0aac7df3988f4.jpg
由此可见,获取的viewTemplateName值是触发漏洞的关键。如果viewTemplateName可控,则可设计viewTemplateName值使之成功被渲染从而执行SPEL表达式。

Thymeleaf ssti的具体场景

第一种其实上面讲过了,就是return的字符串可控的时候,会解析表达式,我们需要关注的是用户传参是否会到达return的string。

第二种是没有return的可控点,但是路由可控

没有return语句的情况下,Thy会从路由获取viemname,本来是直接获取return的字符串作为viewname。这种情况会通过org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator#getViewName方法从请求路径中获取ViewName。处理逻辑如下:
总结该逻辑,取路由中第一个/和最后一个.之间的部分,因此在路由可控的情况下,设计路由形如:
::__spel__.xx即可实现模版注入从而执行任意表达式。

如何防御?

我们现在知道,具体的危险点实际上就是在viewname解析的过程,我们要做的是跳过viewname解析。

  • 1、配置@ResponseBody或者@RestController
    返回值不会被当成viewname处理,而直接作为http响应包返回
  • 2、在方法参数中加上 HttpServletResponse参数
    此时spring会认为已经处理了response响应而不再进行视图解析。不再执行视图解析,也不会走模板引擎;
  • 3、在返回值前面加上 "redirect:"——经RedirectView处理。
  • Spring 会识别这是一个重定向请求,使用 RedirectView;返回值不会传给 ViewResolver(模板引擎);只会拼接成一个 302 Location: 响应头,浏览器跳转
  • 4、模板名严禁可控或必须白名单

FreeMarker

ssti其实大同小异,只不过不同的模板组件会有不同的内置对象,freemarker现在已经是比较少见
必须能控制 模板内容本身 才能造成 SSTI,不能靠模板名。
new

<#assign value="freemarker.template.utility.JythonRuntime"?new()><@value>import os;os.system("calc")</@value>
<#assign value="freemarker.template.utility.Execute"?new()>${value("calc")}

FreeMarker有两个内置函数—— new和api,如上为new用法。
value?api
value?api 提供对 value 的 API(通常是 Java API)的访问,例如 value?api.someJavaMethod() 或 value?api.someBeanProperty。可通过 getClassLoader获取类加载器从而加载恶意类,或者也可以通过 getResource来实现任意文件读取。
但是,当api_builtin_enabled为true时才可使用api函数,而该配置在2.3.22版本之后默认为false。

目前,FreeMarker模版注入已有不错的安全防御措施,可通过配置来禁止解析常见的危险类,同时限制对api函数的使用。

两者区别

比较项FreeMarkerThymeleaf
表达式语言OGNL/自己的表达式(近似 SpEL)基于 Spring EL(SpEL)
默认执行权限非常强大,可直接访问任意类和方法默认受限,需要开启 enable-spring-el 才能使用 SpEL
模板注入方式更容易注入,表达式功能强大默认表达式功能较弱(可配置),安全性稍高
常见利用方式${''.getClass().forName(...)} ${T(java.lang.Runtime).getRuntime().exec(...)}
是否执行副作用✔️ 支持函数调用、副作用强默认模式不支持 class 访问,需显式启用
模板名表达式解析不解析(默认)模板名可被表达式解析(重大区别)

常见功能点

功能模块风险说明
模板预览 / 报表渲染接口最常见的 SSTI,允许用户上传或编辑模板
通知/消息模板编辑器系统可能渲染用户输入中的模板变量
自定义页面名称或片段名视图名、片段名拼接,典型 Thymeleaf 漏洞点
自定义邮件 / 推送模板发送前通常先经过服务端模板渲染
“欢迎语”、“页脚”等文本配置项可能存储后端模板渲染表达式
错误页面跳转路径、预览页面有些使用 ModelAndView(viewName),viewName 可控
打印预览、PDF导出常用 FreeMarker、Velocity、JSP 渲染文档

评论