XSS injection is a very common problem, but it is not difficult to solve it, but there are many things to be aware of. Here is a complete solution.
A common solution in Java is to inherit HttpServletRequestWrapper and then reload methods such as getParameter and getHeader. However, it should be noted that the file upload does not go through HttpServletRequestWrapper, and all xss problems during file Upload need to be solved. If SpringMVC is used, you can directly inherit CommonsMultipartResolver.
If some path (I .e. @ PathVariable annotation) values in the url are used, there are also xss problems. Common Code:
The code is as follows:
@ Controller
@ RequestMapping ("/some ")
Public class SomeController {
@ RequestMapping (value = "/{somepath }")
Public String func (@ PathVariable ("somepath") String somepath ){
DoSomething (path );
Return "";
}
}
When using SpingMVC, I think there should be a class that parses UrlPath to complete this job (just like HandlerMapping and ViewResovler), so that users can customize it, but it does not. The url matching parsing of the source code is in the AbstractHandlerMapping class.The url path does not follow HttpServletRequest, and there are also XSS problems.
The code is as follows:
/ * org.springframework.web.servlet.handler.AbstractHandlerMapping class * /
public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport implements HandlerMapping, Ordered {
private int order = Integer.MAX_VALUE; // default: same as non-Ordered
private Object defaultHandler;
private UrlPathHelper urlPathHelper = new UrlPathHelper ();
private PathMatcher pathMatcher = new AntPathMatcher ();
/ * Omit the code ... * /
The UrlPathHelper class contains two methods, decodePathVariables and decodeMatrixVariables, to extract the path parameter, so a UrlPathHelper is customized to complete the parameter filtering function. Then all AbstractHandlerMapping can use custom UrlPathHelper. However, it should be noted that SpringMVC generates two HandlerMapping-> RequestMappingHandlerMapping and BeanNameUrlHandlerMapping by default. It is generated in the WebMvcConfigurationSupport class. All the urlPathHelper of these two HandlerMappings must be set. There is no direct call interface, so listen to the Spring bean instance Just create it as follows:
/ * Solve the xss attack problem caused by the @PathVariable annotation, note: this class must be initialized by WebApplicationContext * /
public class XssHandlerMappingPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization (Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization (Object bean, String beanName) throws BeansException {
if (bean instanceof AbstractHandlerMapping) {
AbstractHandlerMapping ahm = (AbstractHandlerMapping) bean;
ahm.setUrlPathHelper (new XssUrlPathHelper ());
}
return bean;
}
static class XssUrlPathHelper extends UrlPathHelper {
@Override
public Map <String, String> decodePathVariables (HttpServletRequest request, Map <String, String> vars) {
Map <String, String> result = super.decodePathVariables (request, vars);
if (! CollectionUtils.isEmpty (result)) {
for (String key: result.keySet ()) {
result.put (key, cleanXSS (result.get (key)));
}
}
return result;
}
@Override
public MultiValueMap <String, String> decodeMatrixVariables (HttpServletRequest request,
MultiValueMap <String, String> vars) {
MultiValueMap <String, String> mvm = super.decodeMatrixVariables (request, vars);
if (! CollectionUtils.isEmpty (mvm)) {
for (String key: mvm.keySet ()) {
List <String> value = mvm.get (key);
for (int i = 0; i <value.size (); i ++) {
value.set (i, cleanXSS (value.get (i)));
}
}
}
return mvm;
}
private String cleanXSS (String value) {
return HtmlUtils.htmlEscape (value);
}
}
}
Listen to bean instantiation, and then you can set the UrlPathHelper of all HandlerMapping. Of course, if you use Spring 4.x, you have provided the custom UrlPathHelper configuration:
The code is as follows:
<Mvc: annotation-driven enable-matrix-variables = "false">
<Mvc: path-matching path-helper = "" path-matcher = ""/>
</Mvc: annotation-driven>
In this way, the XSS problem is basically solved at the input source. If the site still has other issues such as js cross-origin, you can also introduce Content-Security-Policy.