系统中默认禁止jsp的访问。允许jsp访问容易导致一些漏洞,最为常见的攻击方式是通过上传jsp文件获取webshell。
在com.jspxcms.core.ShiroConfig
中定义了对jsp
jspx
后缀的过滤。
@Bean
public FilterRegistrationBean jspDispatcherFilterRegistrationBean() {
FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
filterRegistration.setFilter(new JspDispatcherFilter());
filterRegistration.setEnabled(true);
filterRegistration.addInitParameter("prefix", "/jsp");
filterRegistration.addUrlPatterns("*.jsp");
filterRegistration.addUrlPatterns("*.jspx");
filterRegistration.setDispatcherTypes(DispatcherType.REQUEST);
return filterRegistration;
}
其中com.ujcms.common.web.JspDispatcherFilter
就是过滤器。
/**
* 是否允许访问 JSP 或 JSPX 文件。默认 false 。
*/
private boolean allowed = false;
/**
* 请求转发地址前缀。只允许特定目录的 jsp(jspx) 允许被访问。默认为 /jsp 。比如访问 /abc.jsp 通过请求转发实际上访问的文件为 /jsp/abc.jsp 。
*/
private String prefix = "/jsp";
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if (!allowed) {
((HttpServletResponse) response).sendError(HttpServletResponse.SC_FORBIDDEN, "JSP Access Denied");
return;
}
HttpServletRequest req = (HttpServletRequest) request;
String uri = req.getRequestURI();
String ctx = req.getContextPath();
if (StringUtils.isNotBlank(ctx)) {
uri = uri.substring(ctx.length());
}
request.getRequestDispatcher(prefix + uri).forward(request, response);
}
public void init(FilterConfig filterConfig) throws ServletException {
String allowed = filterConfig.getInitParameter("allowed");
if ("true".equals(allowed)) {
this.allowed = true;
}
String prefix = filterConfig.getInitParameter("prefix");
if (StringUtils.isNotBlank(prefix)) {
this.prefix = prefix;
}
}
在这个过滤器中默认不允许任何jsp的直接访问。但对于某些一定需要使用jsp的情况,预留了一个相对安全的访问jsp的方法。就是所有的jsp请求,都转发到/jsp
目录下,这防止了攻击者将jsp文件上传到uploads等目录导致的攻击。因为只有上传到/jsp
目录的jsp文件才能被访问。
可以修改JspDispatcherFilter
的private boolean allowed = true;
。然后将jsp文件放到/jsp
目录中。比如创建/jsp/abc.jsp
文件,访问路径是/abc.jsp
。