Spring 视图操纵漏洞( 二 )


Spring 视图操纵漏洞文章插图
当解析到 ThymeleafViewResolver 这个方法的时候 , 会进入createView , 在这个方法中根据几个条件进行判断 , 比如redirect:或者forward:等等 。 因此我们的ViewName 不满足 , 自然是在resolveViewName处理之后返回了ThymeleafView。
Spring 视图操纵漏洞文章插图
同理在 UrlBasedViewResolver# createView方法当中也是大概根据redirect:或者forward:进行判断 , 因此在 resolveViewName处理之后返回了InternalResourceView。
Spring 视图操纵漏洞文章插图
再看 getBestView , 我们当前的candidateViews 这个list 当中有两个view分别是InternalResourceView和ThymeleafView , 进入处理之后返回的是 ThymeleafView 。 也就是说经过view = resolveViewName(viewName, mv.getModelInternal, locale, request);处理之后 , 返回了我们的视图方法是ThymeleafView , 紧接着就是view.render(mv.getModelInternal, request, response);来到相关的视图方法中进行解析了 。
Spring 视图操纵漏洞文章插图
当然最后的模版解析过程在 org.thymeleaf.spring5.expression.SPELVariableExpressionEvaluator# evaluate 。
exec:347, Runtime (java.lang)...evaluate:263, SPELVariableExpressionEvaluator (org.thymeleaf.spring5.expression)executeVariableExpression:166, VariableExpression (org.thymeleaf.standard.expression)executeSimple:66, SimpleExpression (org.thymeleaf.standard.expression)execute:109, Expression (org.thymeleaf.standard.expression)execute:138, Expression (org.thymeleaf.standard.expression)preprocess:91, StandardExpressionPreprocessor (org.thymeleaf.standard.expression)parseExpression:120, StandardExpressionParser (org.thymeleaf.standard.expression)parseExpression:62, StandardExpressionParser (org.thymeleaf.standard.expression)parseExpression:44, StandardExpressionParser (org.thymeleaf.standard.expression)renderFragment:278, ThymeleafView (org.thymeleaf.spring5.view)render:189, ThymeleafView (org.thymeleaf.spring5.view)No.3
区分
1、加上@ResponseBody注释
//GET /fragment?section=main //GET /fragment?section=__$%7bnew%20java.util.Scanner(T(java.lang.Runtime).getRuntime.exec(%22touch%20executed%22).getInputStream).next%7d__::.x @GetMapping("/fragment") public String fragment(@RequestParam String section) { return "welcome :: " + section; //fragment is tainted }@GetMapping("/safe/fragment") @ResponseBody public String safeFragment(@RequestParam String section) { return "welcome :: " + section; //FP, as @ResponseBody annotation tells Spring to process the return values as body, instead of view name }首先需要了解 @ResponseBody 注释的作用 。
1、该注解用于读取Request请求的body部分数据 , 使用系统默认配置的HttpMessageConverter进行解析 , 然后把相应的数据绑定到要返回的对象上;2、再把HttpMessageConverter返回的对象数据绑定到 controller中方法的参数上 。 而实际上在 RequestMappingHandlerAdapter# handleInternal 返回view的对象的时候返回空 , 找不到模版对象 , 自然也就没有下面的模版解析render 的渲染过程了 。
Spring 视图操纵漏洞文章插图
2、redirect:或者forward:前缀
@GetMapping("/safe/redirect")public String redirect(@RequestParam String url) { return "redirect:" + url; //FP as redirects are not resolved as expressions}@GetMapping("/safe/forward")public String forward(@RequestParam String url) { return "forward:" + url; //FP as redirects are not resolved as expressions}实际上我们前面也聊过了在 AbstractCachingViewResolver# resolveViewName 当中 , 当调用view = createView(viewName, locale);会进入每个模版的 createView方法 , 而这个方法根据前缀redirect:或者forward:进行匹配 , 返回的是RedirectView或者 InternalResourceView , 所以自然不会进行模版解析 。
Spring 视图操纵漏洞文章插图
Spring 视图操纵漏洞文章插图
3、HttpServletResponse标记
在构造方法中指定HttpServletResponse response的org/springframework/web/servlet/DispatcherServlet# doDispatch 方法之后 , 实际上就不返回 modelandView, 也就是说实际上没有进行模版解析 。