Spring Boot escape characters at Request Body for XSS protection

后端 未结 3 1645
别那么骄傲
别那么骄傲 2021-01-07 01:25

I\'m trying to secure my spring boot application using a XSSFilter like this:

public class XSSFilter implements Filter {

    @Override
    public void init(         


        
相关标签:
3条回答
  • 2021-01-07 02:16

    To remove XSS characters you just override AbstractJackson2HttpMessageConverter - this converter has responsibility to read request.inputStream to RequestBody object

    @Component
    public class XSSRequestBodyConverter extends AbstractJackson2HttpMessageConverter {
        public XSSRequestBodyConverter(ObjectMapper objectMapper) {
            super(objectMapper, MediaType.APPLICATION_JSON, new MediaType("application", "*+json"));
        }
    
    @Override
    public Object read(Type type, Class<?> contextClass, HttpInputMessage inputMessage)
            throws IOException, HttpMessageNotReadableException {
    
        Object requestBody = super.read(type, contextClass, inputMessage);
        //Remove xss from requestBody here
        String requestInStr = objectMapper.writeValueAsString(requestBody);
        return objectMapper.readValue(replaceXSSCharacters(requestInStr), Object.class);
    }
    
    
    }
    
    0 讨论(0)
  • 2021-01-07 02:21

    I resolved with a custom class:

    @Configuration
    public class AntiXSSConfig  {
    
        @Autowired()
        public void configeJackson(ObjectMapper mapper) {
            mapper.getFactory().setCharacterEscapes(new HTMLCharacterEscapes());
            mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        }
    
        public static class HTMLCharacterEscapes extends JsonpCharacterEscapes {
    
            @Override
            public int[] getEscapeCodesForAscii() {
                int[] asciiEscapes = CharacterEscapes.standardAsciiEscapesForJSON();
                // and force escaping of a few others:
                asciiEscapes['<'] = CharacterEscapes.ESCAPE_CUSTOM;
                asciiEscapes['>'] = CharacterEscapes.ESCAPE_CUSTOM;
                asciiEscapes['&'] = CharacterEscapes.ESCAPE_CUSTOM;
                asciiEscapes['"'] = CharacterEscapes.ESCAPE_CUSTOM;
                asciiEscapes['\''] = CharacterEscapes.ESCAPE_CUSTOM;
                return asciiEscapes;
            }
    
            @Override
            public SerializableString getEscapeSequence(int ch) {
                switch (ch) {
                    case '&' : return new SerializedString("&#38;");
                    case '<' : return new SerializedString("&#60;");
                    case '>' : return new SerializedString("&#62;");
                    case '\"' : return new SerializedString("&#34;");
                    case '\'' : return new SerializedString("&#39;");
                    default : return super.getEscapeSequence(ch);
                }
            }
        }
    }
    

    It covers all the cases.

    0 讨论(0)
  • 2021-01-07 02:21
    1. Have a local String field in XSSRequestWrapper which holds the cleaned-up body (probably not suitable for large bodies).
    2. Populate this field in the constructor by reading request.getInputStream() and cleaning up the body the same way as parameters.
    3. Override getInputStream and getReader methods of HttpServletRequestWrapper, and construct an InputStream (string -> byte array -> ByteArrayInputStream) and Reader (StringReader) from the String field and return them respectively. Maybe cache the constructed InputStream and Reader objects for better performance for when the methods are called repeatedly.

    You may also be interested in cleaning up JSON when it is being deserialized into Java object.

    0 讨论(0)
提交回复
热议问题