본문 바로가기

Web Development/Secure Coding

Spring에서 JSON에 XSS Filter 처리하기

Spring Framework를 사용하여 개발한다면 Lucy-xss-servlet-filter 또는 전자정부프레임워크의 HtmlTagfilter로 XSS 공격 방지하는 경우를 볼 수 있다.

하지만 위 방법들은 기본적으로 Request Parameter에 대해서만 필터링 가능하고 raw body(@RequestBody)로 전달되는 데이터에는 필터링 처리가 되지 않는 것을 확인하였다.

@RequestBody로 전달되는 데이터의 예는 json이 있다.

 

그럼 json 데이터에 xss filter를 적용하려면 어떻게 해야 할까?

구글링으로 찾아본 결과 아래와 같은 방법이 있다.

 

  • objectMapper를 가진 FactoryBean 생성 후 dispatcher-servlet.xml or servlet.xml에서 처리하기
  
import org.apache.commons.lang3.StringEscapeUtils;
import org.springframework.beans.factory.FactoryBean;
import com.fasterxml.jackson.core.SerializableString;
import com.fasterxml.jackson.core.io.CharacterEscapes;
import com.fasterxml.jackson.core.io.SerializedString;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

public class HtmlEscapingObjectMapperFactory implements FactoryBean {

    private final ObjectMapper objectMapper;
	public HtmlEscapingObjectMapperFactory() {

        objectMapper = new ObjectMapper();

        objectMapper.getFactory().setCharacterEscapes(new HTMLCharacterEscapes());

        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

    }
  
    @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)));
        }
    }
}
  
<bean id="htmlEscapingObjectMapper" class="~.HtmlEscapingObjectMapperFactory" />
	<mvc:annotation-driven>
	    <mvc:message-converters>
	        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" >
	        	<property name="objectMapper" ref="htmlEscapingObjectMapper"></property>
	        </bean>
	    </mvc:message-converters>
	</mvc:annotation-driven>

출처: https://lahuman.jabsiri.co.kr/155 [lahuman & jabsiri 노트]

 

이외에도 여러가지 방법이 있는데 계속 추가하면서 공부해야겠다.

반응형