[TIL] XSS
XSS란?
권한 없는 사용자가 웹 사이트에 악성 스크립트를 삽입하는 공격 방법. 주로 게시판 같은 곳에 스크립트가 포함된 게시글을 작성하는 형태로 이루어진다.
xss 실습
예제 1)
예제 2)
글 작성자가 HTML 코드를 삽입하여 글을 읽는 사람의 브라우저에서 실행되게 하는 원리이다.
게시판에 쓴 alert가 클라이언트에서 작동.
이게 가능한 이유는 자바스크립트는 클라이언트측 언어이기때문에 실행될 수 있다. Test라 alert 실행문을 넣었지만 HTML 코드로 악성코드를 삽입등 클라이언트측에 치명적인 공격이 가능하다 CSRF는 서버가 목표지만 XSS는 이용자가 목표이다.
대응법
1) script 문장에 존재한 특수문자를 메타캐릭터로 변환
< ---- <
> ---- >
( ---- (
) ---- )
# ---- #
& ---- &
2.Contents 구문 사용
3.Replace 구문 사용
잘모르겠다. 네이버 lucy-xss-filter 를 적용시켰다.
1) 의존성 주입부터.
2)lucy-xss-servlet-filter-rule.xml 생성 (resource폴더에)
<?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에서 들어오는 globalParameter 파라메터는 필터링 되지 않으며
또한 globalPrefixParameter1로 시작하는 파라메터도 필터링 되지 않는다.
globalPrefixParameter2는 필터링 되며 globalPrefixParameter3은 필터링 되지 않지만
더 정확한 표현이 가능하므로 globalPrefixParameter2, globalPrefixParameter3과 같은 불분명한 표현은 사용하지 않는 것이 좋다. -->
<params>
<param name="globalParameter" useDefender="false" />
<param name="globalPrefixParameter1" usePrefix="true" useDefender="false" />
<param name="globalPrefixParameter2" usePrefix="true" />
<param name="globalPrefixParameter3" usePrefix="false" useDefender="false" />
</params>
</global>
<!-- url 별 필터링 룰 선언 -->
<url-rule-set>
<!-- url disable이 true이면 지정한 url 내의 모든 파라메터는 필터링 되지 않는다. -->
<url-rule>
<url disable="true">/disableUrl1.do</url>
</url-rule>
<!-- url disable이 false인 설정은 기본이기 때문에 불필요하다. 아래와 같은 불필요한 설정은 하지 않는다.-->
<url-rule>
<url disable="false">/disableUrl2.do</url>
</url-rule>
<!-- url disable이 true이면 지정한 url 내의 모든 파라메터가 필터링 되지 않기 때문에 <params> 로 선언한 설정은 적용되지 않는다.
아래와 같은 불필요한 설정은 하지 않는다. -->
<url-rule>
<url disable="true">/disableUrl3.do</url>
<params>
<param name="query" useDefender="false" />
<param name="prefix1" usePrefix="true" />
<param name="prefix2" usePrefix="false" useDefender="false" />
<param name="prefix3" usePrefix="true" useDefender="true" />
<param name="prefix4" usePrefix="true" useDefender="false" />
<param name="prefix5" usePrefix="false" useDefender="true" />
</params>
</url-rule>
<!-- url disable이 false인 설정은 기본이기 때문에 불필요하다. <params> 선언한 설정은 적용이 된다.-->
<url-rule>
<url disable="false">/disableUrl4.do</url>
<params>
<!-- disableUrl4.do 의 query 파라메터와 prefix4로 시작하는 파라메터들은 필터링 되지 않는다.
usePrefix가 false, useDefender가 true인 설정은 기본이기 때문에 불필요하다. -->
<param name="query" useDefender="false" />
<param name="prefix1" usePrefix="true" />
<param name="prefix2" usePrefix="false" useDefender="false" />
<param name="prefix3" usePrefix="true" useDefender="true" />
<param name="prefix4" usePrefix="true" useDefender="false" />
<param name="prefix5" usePrefix="false" useDefender="true" />
<param name="prefix6" usePrefix="true">
<defender>xssSaxFilterDefender</defender>
</param>
</params>
</url-rule>
<!-- url1 내의 url1Parameter는 필터링 되지 않으며 또한 url1PrefixParameter로 시작하는 파라메터도 필터링 되지 않는다. globalParameter는
상위 글로벌 global 설정에 동일한 이름으로 되어있지만 url-rule 설정을 더 우선하여 따른다. -->
<url-rule>
<url>/url1.do</url>
<params>
<param name="url1Parameter" useDefender="false" />
<param name="url1PrefixParameter" usePrefix="true" useDefender="false" />
<param name="globalParameter"/>
</params>
</url-rule>
<!-- url2 내의 url2Parameter1만 필터링 되지 않으며 url2Parameter2는 xssSaxFilterDefender를 사용해 필터링 한다. -->
<url-rule>
<url>/url2.do</url>
<params>
<param name="url2Parameter1" useDefender="false">
<defender>xssPreventerDefender</defender>
</param>
<param name="url2Parameter2">
<defender>xssSaxFilterDefender</defender>
</param>
<param name="url2Parameter3">
<defender>xssPreventerDefender</defender>
</param>
</params>
</url-rule>
</url-rule-set>
</config>
3) 메인메소드에 빈 생성 후 적용
public static void main(String[] args) {
SpringApplication.run(HwkspringApplication.class, args);
}
@Bean
public FilterRegistrationBean xssEscapeServletFilter() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(new XssEscapeServletFilter());
registrationBean.setOrder(1); // @Order로 처리.
registrationBean.addUrlPatterns("/*");
return registrationBean;
}
lucy 필터는 form data 전송 방식엔 유효, @RequestBody로 전달되는 JSON 요청은 처리는 하지않는다.
4)HTMLCharacterEscapes 클래스 생성( escape 할 character를 지정해주는 클래스 생성.)
package com.sparta.hwkspring;
import com.fasterxml.jackson.core.SerializableString;
import com.fasterxml.jackson.core.io.CharacterEscapes;
import com.fasterxml.jackson.core.io.SerializedString;
import org.apache.commons.text.StringEscapeUtils;
public class HTMLCharacterEscapes extends CharacterEscapes {
private final int[] asciiEscapes;
public HTMLCharacterEscapes() {
// 1. XSS 방지 처리할 특수 문자 지정
asciiEscapes = CharacterEscapes.standardAsciiEscapesForJSON();
asciiEscapes['<'] = CharacterEscapes.ESCAPE_CUSTOM;
asciiEscapes['>'] = CharacterEscapes.ESCAPE_CUSTOM;
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;
}
@Override
public SerializableString getEscapeSequence(int ch) {
return new SerializedString(StringEscapeUtils.escapeHtml4(Character.toString((char) ch)));
}
}
5)configuration 클래스 생성
package com.sparta.hwkspring;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
@Slf4j
@RequiredArgsConstructor
@Configuration
public class WebMvcConfig {
private final ObjectMapper objectMapper;
@Bean
public MappingJackson2HttpMessageConverter jsonEscapeConverter() {
ObjectMapper copy = objectMapper.copy();
copy.getFactory().setCharacterEscapes(new com.sparta.hwkspring.HTMLCharacterEscapes());
return new MappingJackson2HttpMessageConverter(copy);
}
}
적용 후
게시글에 코드도 보이고 alert도 뜨지않는다 성공.
참고 사이트
Author And Source
이 문제에 관하여([TIL] XSS), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@bonooo/TIL-XSS저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)