Java安全 - Spring Web MVC 请求解析过程
前言
主要是有师傅对一些鉴权的Spring不太懂,并且自身也有不太清楚的地方于是跟下 Spring Web MVC 请求解析过程
过程
当我们发出请求的时候,会被
\spring-webmvc-5.3.23.jar!\org\springframework\web\servlet\DispatcherServlet.java#service() 所拦截(在父类FrameworkServlet实现了)
获取请求方式,只要不是PATCH的请求就会去调用FrameworkServlet的父类HttpServletBean的父类HttpServlet的service方法
这里实际上是根据不同的请求方法,调用对应的方法,例如GET请求会调用doGet方法
最后调用processRequest方法
在这里调用了doService方法之后
还继续把请求包和返回包传入doDispatch方法中
在doDispatch方法中,首先会对multipart请求进行处理,然后获取对应的mappedHandler,如何获取呢,其实就是使用了getHandler方法
跟进getHandler方法,发现是循环调用handlerMappings数组的getHandler方法对我们的请求报文进行处理
跟进第一个值的getHandler方法,也就是\spring-webmvc-5.3.23-sources.jar!\org\springframework\web\servlet\handler\AbstractHandlerMapping.java#getHandler(),他先进行了一次getHandlerInternal方法对请求的报文进行处理
跟进getHandlerInternal方法,发现是从request对象中获取请求的path
跟进initLookupPath,初始化请求映射的路径,并且通过
1 | |
最后获取到我们请求的路径/hello;
接下来就去用到UrlPathHelper工具类的removeSemicolonContent方法,对于当前处理的URI,如果设置了setRemoveSemicolonContent属性为true,则继续把路径丢给removeSemicolonContentInternal方法,否则删除Jsessionid
然后这个方法其实就是去寻找; 并且删除掉;
这里可以仔细去看看他的删除逻辑,也可以本地写个demo测一下即可,我本地测了一下之后解释如下
- 先找到
;的位置 比如/jsp/files;.js 他就会找到;之前一共有几位 这里就是10位 - 然后接下来就是做判断,判断
;后面是否存在/,如果存在/,则继续索引,比如/hello/..;1111/hello 这里就是会索引到第14位,然后把索引到的两个数字丢进delete去截取(简单理解为就是删掉;之后到/的所有字符串) - 如果不存在
/就直接返回;之前的东西就行
所以返回的结果就会删掉了;以及其后面的内容了
接着返回了我们请求的路径后就把我们的路径作为参数给到lookupHandlerMethod 方法调用,首先直接根据路径获取对应的Mapping,获取不到的话调用addMatchingMappings遍历所有的ReuqestMappingInfo对象并进行匹配
跟进addMatchingMappings ,遍历识别到的ReuqestMappingInfo对象并进行匹配
再去调用 getMatchingMapping方法
跟进getMatchingCondition方法,getMatchingCondition不同版本的实现也是不一样的,高版本会使用PathPattern来进行URL匹配(不同版本会有差异,在 2.6之前,默认使用的是AntPathMatcher进行的字符串模式匹配)
接着走到核心点再次调用getMatchingCondition方法
进入到\spring-webmvc-5.3.23-sources.jar!\org\springframework\web\servlet\mvc\condition\PathPatternsRequestCondition.java#getMatchingCondition()
如果模式与路径相等,直接返回模式,否则进行后缀模式匹配,这里涉及到两个属性SuffixPatternMatch&TrailingSlashMatch,根据这两个属性的boolean值会调用pathMatcher#match方法进行进一步的匹配
这里就小跟一下罢了,剩下的就要再深层点了
审计案例
海康威视综合安防系统
POC
1 | |
CAS的配置如下,其实就是以下的接口或者说是后缀是不鉴权的
找到上传的控制器
/bin/tomcat/apache-tomcat/webapps/center/WEB-INF/classes/com/hikvision/center/module/faq/controller/KnowledgeController.java#uploadFile()
发现是把上传的文件名取出来直接丢到了son = this.knowledgeService.uploadFile(file);中
跟进knowledgeService.uploadFile
发现也就是单纯拼接文件名并没有过滤,但是因为会鉴权,然后因为CAS的配置文件的问题,所以我们可以巧妙的利用SpringbootWebMVC的removeSemicolonContentInternal通过;来与不鉴权的后缀进行拼接从而映射到该路由下
/center/api/files -> 鉴权
/center/api/files;.js -> 不鉴权 -> 可以删除;.js