복붙노트

[SPRING] Spring 3.2.4에서 XSS를 이스케이프 처리하는 @RequestBody가있는 @InitBinder

SPRING

Spring 3.2.4에서 XSS를 이스케이프 처리하는 @RequestBody가있는 @InitBinder

내 메소드에서 @RequestBody 주석 인자가 다음과 같이 나타납니다.

@RequestMapping(value = "/courses/{courseId}/{name}/comment", method = RequestMethod.POST)
@ResponseStatus(HttpStatus.OK)
public @ResponseBody CommentContainer addComment(@PathVariable Long courseId,
                          @ActiveAccount Account currentUser,
                          @Valid @RequestBody AddCommentForm form,
                          BindingResult formBinding,
                          HttpServletRequest request) throws RequestValidationException {

.....
}

그런 다음 동일한 컨트롤러에 @InitBinder 주석 메서드가 있습니다.

@InitBinder
public void initBinder(WebDataBinder dataBinder) {
    dataBinder.registerCustomEditor(AddCommentForm.class, new StringEscapeEditor());
}

내 StringEscapeEditor가 실행되고 있지 않습니다. 하지만 내 initBinder 메서드입니다. 그래서 내 양식을 이스케이프 편집기에 매핑하지 않습니다. 이 스레드를 읽은 직후에 (@RequestMapping은 @InitBinder에서 지원하지 않는 것 같습니다.)

spring mvc @InitBinder는 ajax 요청을 처리 할 때 호출되지 않습니다.

그리고 @PathVariable 문자열을 매핑하고 편집기가 작동하는지 테스트했습니다.

내 바인딩의 대부분은 @RequestBody로 끝났기 때문에 이것은 내 응용 프로그램에서 큰 문제이며 일부 사용자 지정 바인딩을 적용 할 수 있다면 좋을 것입니다.

이 문제를 해결하는 가장 일반적인 방법은 무엇입니까? 스크립트 공격에 대한 입력 데이터를 피할 수 있습니다.

해결법

  1. ==============================

    1.XSS를 탈출하기 위해서는 정확한 탈출이 출력 문서에 의존하기 때문에 데이터를 출력하는 동안 이스케이프 처리를하는 것이 좋습니다.

    XSS를 탈출하기 위해서는 정확한 탈출이 출력 문서에 의존하기 때문에 데이터를 출력하는 동안 이스케이프 처리를하는 것이 좋습니다.

    @ResponseBody에 의해 생성 된 JSON 응답이 클라이언트에 의해 직접 소비되고 XSS가 컨텐트를 이스케이프 할 기회가없는 경우 JacksonMessageConverter를 사용자 정의하여 문자열에서 XSS 이스케이프를 수행 할 수 있습니다.

    다음과 같이 JacksonMessageConverter를 사용자 정의 할 수 있습니다.

    1) 먼저 우리는 커스텀 객체 매퍼를 생성 할 ObjectMapper 팩토리를 생성합니다 :

    public class HtmlEscapingObjectMapperFactory implements FactoryBean<ObjectMapper> {
    
        private final ObjectMapper objectMapper;
    
        public HtmlEscapingObjectMapperFactory() {
            objectMapper = new ObjectMapper();
            objectMapper.getJsonFactory().setCharacterEscapes(new HTMLCharacterEscapes());
        }
    
        @Override
        public ObjectMapper getObject() throws Exception {
            return objectMapper;
        }
    
        @Override
        public Class<?> getObjectType() {
            return ObjectMapper.class;
        }
    
        @Override
        public boolean isSingleton() {
            return true;
        }
    
        public static class HTMLCharacterEscapes extends CharacterEscapes {
    
            private final int[] asciiEscapes;
    
            public HTMLCharacterEscapes() {
                // start with set of characters known to require escaping (double-quote, backslash etc)
                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;
            }
    
    
            @Override
            public int[] getEscapeCodesForAscii() {
                return asciiEscapes;
            }
    
            // and this for others; we don't need anything special here
            @Override
            public SerializableString getEscapeSequence(int ch) {
                return new SerializedString(StringEscapeUtils.escapeHtml4(Character.toString((char) ch)));
    
            }
        }
    }
    

    (HtmlCharacterEscapes에 대한 영감은 Spring MVC 및 Jackson Mapper를 사용한 HTML 이스케이프)

    2) 그런 다음 사용자 정의 객체 매퍼 (xml config의 예제)를 사용하는 메시지 변환기를 등록합니다.

    <bean id="htmlEscapingObjectMapper" class="com.example.HtmlEscapingObjectMapperFactory" />
    
    <mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" p:objectMapper-ref="htmlEscapingObjectMapper" />
        </mvc:message-converters>
    </mvc:annotation-driven>
    

    @ResponseBody에 의해 생성 된 모든 JSON 메시지는 HTMLCharacterEscapes에 지정된대로 이스케이프 된 문자열을 가져야합니다.

    문제에 대한 대안 솔루션 :

    출력 이스케이프 처리 외에도 시스템 / 데이터베이스에 입력하고 싶지 않은 일부 내용을 차단하기 위해 표준 유효성 검사 방법을 사용하여 일부 입력 유효성 검사를 수행하는 것이 유용 할 수 있습니다.

    편집 : JavaConfig

    나는 이것을 시도하지는 않았지만 자바 설정에서 이와 같이 작동해야한다. (이 경우에는 모든 것을 설정할 수 있기 때문에 위의 Factory Bean은 필요 없다) :

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        super.configureMessageConverters(converters);
        converters.add(buildHtmlEscapingJsonConverter());
    
    }
    
    private MappingJacksonHttpMessageConverter buildHtmlEscapingJsonConverter() {
        MappingJacksonHttpMessageConverter htmlEscapingConverter = new MappingJacksonHttpMessageConverter();
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.getJsonFactory().setCharacterEscapes(new HTMLCharacterEscapes());
        htmlEscapingConverter.setObjectMapper(objectMapper);
        return htmlEscapingConverter;       
    }
    

    일반적으로 구성되어있는 다른 non-json 기본 메시지 변환기 (예 : XML 변환기 등 ..)가 손실 될 수 있으며 필요하면 수동으로 추가해야합니다 (기본적으로 활성화되어있는 것을 볼 수 있음). 여기 섹션 2.2 : http://www.baeldung.com/spring-httpmessageconverter-rest)

  2. from https://stackoverflow.com/questions/25403676/initbinder-with-requestbody-escaping-xss-in-spring-3-2-4 by cc-by-sa and MIT license