오늘은 XSS(Cross Site Scripting)공격에 대한 보안처리를 해보겠습니다
웹을 구현할때는 가장 기본적으로 XSS와 CSRF에 대한 보안처리를 해줘야합니다
스프링 시큐리티 사용시에는 CSRF가 default값으로 enable되어있으며
데이터를 추가하거나 변경 삭제 하는경우 REST API를 사용한다면 서버쪽의 세션이나
브라우저 쿠키에 의존하지 않으므로 크게 신경쓰지 않아도 되지만 XSS에 대해서는
꼭 따로 보안처리를 해줘야합니다.
XSS공격이란 공격자가 상대방의 브라우저에 스크립트가 실행되도록 해
사용자의 세션을 가로채거나, 웹사이트를 변조하거나, 악의적 콘텐츠를 삽입하거나,
피싱 공격을 진행하는 것을 뜻하는데 예를 들어 게시글이나 댓글과 같은곳에
<script>
나 <img src>
같은 코드를 입력하여 관리자가 의도하지 않은 상황을
발생시키는것을 말합니다
XSS공격은 사용자가 텍스트를 입력가능한 모든곳에서 이루어지는데 만약 리뷰작성공간에
악의적으로 경고창을 실행시키는 스크립트를 넣는다면 다른 사용자가 리뷰탭을 클릭했을시
다음과 같은 경고창을 보게 됩니다
해당 매장의 리뷰에 접근하는 모든 사용자한테 위와 같은 경고창이 뜨게 됩니다
리뷰화면뿐만 아니라 가게정보, 메뉴정보 같이 텍스트를 입력할수 있는
모든곳에서 다양한 공격이 가능하므로 우리는 이것에 대한 보안처리를 해줘야합니다
이에 대한 여러가지 방법이 있는데 프론트쪽에서 <script>
와 같은 특정 문자열을
입력받지 못하는 방법과 서버쪽에서 사용자가 입력한 값에서 특정 문자열이 존재하는지
확인하여 강제로 바꾸는 방법, 이스케이프를 사용하여 문자열 처리 같은 방법이 있습니다
하지만 직접 필터를 만들어 다양한 XSS공격에 대한 처리를 하는것은 쉽지 않으며
새로운 공격이 발견될때마다 그에 대한 처리를 해줘야 하는 문제점이 있습니다
따라서 네이버에서 다양한 XSS공격을 보안하기 위해 개발한 오픈소스인
Lucy Xss Filter를 사용하면 다양한 XSS공격을 쉽게 방지할수 있습니다
해당 라이브러리를 사용하기 위해 pom.xml에 Lucy Filter를 추가해줍시다
<!-- Lucy-xss-servlet-filter -->
<dependency>
<groupId>com.navercorp.lucy</groupId>
<artifactId>lucy-xss-servlet</artifactId>
<version>2.0.1</version>
</dependency>
이제 스프링 Ioc 컨테이너가 해당 필터를 관리할수 있도록 bean등록을 해줘야합니다
//Lucy Xss filter 적용
@Bean
public FilterRegistrationBean<XssEscapeServletFilter> getFilterRegistrationBean(){
FilterRegistrationBean<XssEscapeServletFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new XssEscapeServletFilter());
registrationBean.setOrder(1);
registrationBean.addUrlPatterns("/*");
return registrationBean;
}
마지막으로 application.yml가 있는 src/main/resource 폴더안에
lucy-xss-servlet-filter-rule.xml를 추가해주도록 합시다
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://www.navercorp.com/lucy-xss-servlet">
<defenders>
<!-- XssPreventer 등록 -->
<defender>
<name>xssPreventerDefender</name>
<class>com.navercorp.lucy.security.xss.servletfilter.defender.XssPreventerDefender
</class>
</defender>
<!-- XssSaxFilter 등록 -->
<defender>
<name>xssSaxFilterDefender</name>
<class>com.navercorp.lucy.security.xss.servletfilter.defender.XssSaxFilterDefender
</class>
<init-param>
<param-value>lucy-xss-sax.xml</param-value> <!-- lucy-xss-filter의 sax용 설정파일 -->
<param-value>false</param-value> <!-- 필터링된 코멘트를 남길지 여부, 성능 효율상 false 추천 -->
</init-param>
</defender>
<!-- XssFilter 등록 -->
<defender>
<name>xssFilterDefender</name>
<class>com.navercorp.lucy.security.xss.servletfilter.defender.XssFilterDefender
</class>
<init-param>
<param-value>lucy-xss.xml</param-value> <!-- lucy-xss-filter의 dom용 설정파일 -->
<param-value>false</param-value> <!-- 필터링된 코멘트를 남길지 여부, 성능 효율상 false 추천 -->
</init-param>
</defender>
</defenders>
<!-- default defender 선언, 별다른 defender 선언이 없으면 default defender를 사용해 필터링
한다. -->
<default>
<defender>xssPreventerDefender</defender>
</default>
<!-- global 필터링 룰 선언 -->
<global>
<!-- 모든 url에서 들어오는 'gParam' 파라미터는 필터링 되지 않으며 또한 'g'로 시작하는 파라미터도 필터링 되지
않는다. -->
<params>
<param name="gParam" useDefender="false" />
<param name="g" usePrefix="true" useDefender="false" />
</params>
</global>
<!-- URL 별 필터링 룰 선언 -->
</config>
이제 적용이 잘되었는지 확인해보면 <,>가 이스케이프 문자로 변환되어 저장되었음을 알수있습니다