好久没有写博客了,这两天遇到一个关于url编码的问题,做一个记录
需求是这样的;
系统遭受不法人员攻击,老大系统系统写一个过滤器,当有安全攻击的时候,直接通过配置的方式禁止该接口的使用
本来以为很简单 ,直接写了一个定时加载的功能,读取配置,然后与请求过来的url进行对比即可,用浏览器测试都没有问题,但是经过安全的时候,问题来了,在浏览器中会url自动的解析,但是在当在抓起工具中输入以下地址,仍然能请求道相应的请求,
/product/./queryChannelProductInfo
/product/123/../queryChannelProductInfo
/product%2fqueryChannelProductInfo
从表面现象可以看出,服务器底层还有一个层与浏览器做了同样的规则处理
一开始处理的方式 , 获取器Dispatcher,通过反射然后获取器url,然后在进行比较
RequestDispatcher dispatcher = arg0.getRequestDispatcher(reqUrl);
@SuppressWarnings("deprecation")
Field path = arg0.getRequestDispatcher(URLDecoder.decode(reqUrl)).getClass().getDeclaredFields()[16];
path.setAccessible(true);
path.get(dispatcher);
String dispatcherUrl =(String) path.get(dispatcher);
if (new AntPathMatcher().match(strUrl,dispatcherUrl)) {
logger.warn(reqUrl + "have no authority for rquest");
return;
}
这种方法解决了./ ../这种方式,但是url编码的格式仍然可以绕过
一时分析,框架用的是springmvc 应该是在内容的处理导致的 ,于是开始分析spring mvc 的源码
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
processedRequest = this.checkMultipart(request);
multipartRequestParsed = processedRequest != request;
mappedHandler = this.getHandler(processedRequest, false);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
this.noHandlerFound(processedRequest, response);
return;
}
......
}
@Deprecated
protected HandlerExecutionChain getHandler(HttpServletRequest request, boolean cache) throws Exception {
return this.getHandler(request);
}
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
Iterator i$ = this.handlerMappings.iterator();
HandlerExecutionChain handler;
do {
if (!i$.hasNext()) {
return null;
}
HandlerMapping hm = (HandlerMapping)i$.next();
if (this.logger.isTraceEnabled()) {
this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name '" + this.getServletName() + "'");
}
handler = hm.getHandler(request);
} while(handler == null);
return handler;
}
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
Object handler = getHandlerInternal(request);
if (handler == null) {
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}
if (handler instanceof String) {
String handlerName = (String) handler;
handler = getApplicationContext().getBean(handlerName);
}
return getHandlerExecutionChain(handler, request);
}
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
HandlerExecutionChain chain = new HandlerExecutionChain(handler);
chain.addInterceptors(getAdaptedInterceptors());
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
for (MappedInterceptor mappedInterceptor : this.mappedInterceptors) {
if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
}
return chain;
}