Skip to content
Advertisement

ControllerAdvice @InitBinder setDisallowedFields doesn’t work

A JAVA project has been built with spring boot version 2.5.3.

Due to the “Spring4shell” (CVE-2022-22965) security risk, we have to take mitigation actions.

It’s not possible to upgrade the Spring Boot version since several other dependencies are incompatible with the latest Spring Boot version. So, it has been decided to apply a suggested workaround according to https://www.springcloud.io/post/2022-03/spring-framework-rce-early-announcement/#gsc.tab=0

According to the guide, there are 2 workarounds suggested.

  1. Setting disallowedFields on WebDataBinder through an @ControllerAdvice method
@ControllerAdvice
@Order(Ordered.LOWEST_PRECEDENCE)
public class BinderControllerAdvice {

    @InitBinder
    public void setAllowedFields(WebDataBinder dataBinder) {
         String[] denylist = new String[]{"class.*", "Class.*", "*.class.*", "*.Class.*"};
         dataBinder.setDisallowedFields(denylist);
    }

}
  1. Extend RequestMappingHandlerAdapter to update the WebDataBinder:
@Bean
    public WebMvcRegistrations mvcRegistrations() {
        return new WebMvcRegistrations() {
            @Override
            public RequestMappingHandlerAdapter getRequestMappingHandlerAdapter() {
                return new ExtendedRequestMappingHandlerAdapter();
            }
        };
    }


    private static class ExtendedRequestMappingHandlerAdapter extends RequestMappingHandlerAdapter {

        @Override
        protected InitBinderDataBinderFactory createDataBinderFactory(List<InvocableHandlerMethod> methods) {

            return new ServletRequestDataBinderFactory(methods, getWebBindingInitializer()) {

                @Override
                protected ServletRequestDataBinder createBinderInstance(
                        Object target, String name, NativeWebRequest request) throws Exception {
                    
                    ServletRequestDataBinder binder = super.createBinderInstance(target, name, request);
                    String[] fields = binder.getDisallowedFields();
                    List<String> fieldList = new ArrayList<>(fields != null ? Arrays.asList(fields) : Collections.emptyList());
                    fieldList.addAll(Arrays.asList("class.*", "Class.*", "*.class.*", "*.Class.*"));
                    binder.setDisallowedFields(fieldList.toArray(new String[] {}));
                    return binder;
                }
            };
        }
    }

Both of the approaches have been tried but none of them could reject the following request.

HOST:PORT/path?class.module.classLoader.URLs%5B0%5D=0

What can be the missing point of our approach?

Advertisement

Answer

Request will not be rejected by setting values to webDataBinder.setDisallowedFields().

WebDataBinder provides two methods setAllowedFields and setDisallowedFields to set the list of attribute names which can be and cannot be used in data binding process for model objects. This validation will happen in org.springframework.validation.DataBinder::doBind method. inside the doBind method disallowed fields will be removed from the field list

Advertisement