스프링에서 XSS 처리는 어떻게 하나요~

10,372 views
Skip to first unread message

StyLe_jG

unread,
May 23, 2011, 10:01:40 PM5/23/11
to Korea Spring User Group
초보 개발자 입니다.

이번에 스프링을 통한 프로젝트를 진행하고 있는데요, XSS 처리를 어떻게 할지 고민이 되어 글을 올립니다.

기존의 다른 프로젝트에서는 HttpServletRequest 의 파라미터 들을 가로채서 <, > 같은 것들을 치환해 주면서 처리
했는데요.

스프링에서 더 좋은 방법, 혹은 노하우가 있으시면 공유 부탁 드립니다.

그리고, 혹시 스프링 인터셉터를 통해 컨트롤러로 들어오는 모든 파라미터를 가로채서 처리하는 방법으로 XSS를 처리하면 문제가 없
을지, 이렇게 적용해보신 분들의 답변 기다리겠습니다.

고수님의 손길을 기다립니다.ㅜㅜ

선영욱

unread,
May 23, 2011, 10:12:11 PM5/23/11
to ks...@googlegroups.com
제가 적용했던 방법과 동일한 XSS 처리 방법을 고민하고 계신거 같습니다.
 
일단 저도 스프링 인터셉터에서 컨트롤러로 들어오는 모든 파라메터 값에 대해서 XSS 체크를 해서 유효하지 않은 경우 지정된 페이지로 이동을 하도록 했는데요.
 
체크 로직은 <, >을 치환하는 방법이 아닌 문자열 비교로 유효하지 않은 단어를 찾도록 했습니다.(고객사의 요청)
 
다만 이 방법은 알려지지 않은 XSS에 유효하지 않은 단어가 생기는 것을 관리자가 일일이 등록해주어야 하는 방법이라서 그다지 추천드리지 않습니다.
 
servlet.xml 설정 중 일부
 
 <bean id="xssHandlerInterceptor" class="xxx.interceptor.XSSHandlerInterceptor">
        <property name="invaildWordMappings">
            <props>
                <prop key="javascript">javascript</prop>
                <prop key="vbscript">vbscript</prop>
                <prop key="script">script</prop>
                ...
            </props>
        </property>
 </bean>
 
    <bean id="simpleUrlMapping"
        class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="interceptors">
        <list>
          <ref local="xssHandlerInterceptor" />
        </list>
        </property>
        <property name="order">
            <value>0</value>
        </property>
     </bean>
 
소스
 
public class XSSHandlerInterceptor extends HandlerInterceptorAdapter {
 
 private Properties invaildWordMappings;
 
 public void setInvaildWordMappings(Properties invaildWordMappings) {
  this.invaildWordMappings = invaildWordMappings;
 }
 /**
  * 전처리
  * @param request
  * @param response
  * @param handler
  * @return
  */
 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
     throws Exception {
   
  for(Enumeration names = request.getParameterNames(); names.hasMoreElements();) {
   String name = (String)names.nextElement();
   String val = StringUtil.nvl(request.getParameter(name));
   
   String ret = getMatchInvaildWord(val);
   if(null != ret){
    String message = name+" 항목에 유효하지 않은 단어("+ret+")가 포함되어 크로스 서버 스크립팅(XSS)검사에 실패하였습니다.";
    Exception e = new RuntimeException(message);
    request.setAttribute("error", e);
    request.setAttribute("uri", request.getRequestURI());
    request.setAttribute("message", message);
    request.setAttribute("exception_type", "RuntimeException");
    throw e;
   }
  }
    
  return true;
 }
 
 /**
  * 유효하지 않은 단어가 포함되었는지 확인
  * @param val
  * @return
  */
 public boolean existInvaildWord(String val) throws Exception {
  boolean existInvaildWord = false;
  if(null != getMatchInvaildWord(val)){
   existInvaildWord = true;
  }
  return existInvaildWord;
 }
 
 /**
  * 유효하지 않은 단어가 포함되었다면 어떤 단어인지 반환
  * @param val
  * @return
  */
 public String getMatchInvaildWord(String val) throws Exception {
  for(Enumeration names = invaildWordMappings.propertyNames(); names.hasMoreElements();) {
   String key = (String) names.nextElement();
   String invaildWord = invaildWordMappings.getProperty(key);
   
   if(val.indexOf(invaildWord) > -1){
    return invaildWord;
   }
  }
  return null;
 }
}
 
2011년 5월 24일 오전 11:01, StyLe_jG <cresp...@gmail.com>님의 말:

--
Google 그룹스 'Korea Spring User Group' 그룹에 가입했으므로 본 메일이 전송되었습니다.
이 그룹에 게시하려면 ks...@googlegroups.com(으)로 이메일을 보내세요.
그룹에서 탈퇴하려면 ksug+uns...@googlegroups.com로 이메일을 보내주세요.
더 많은 옵션을 보려면 http://groups.google.com/group/ksug?hl=ko에서 그룹을 방문하세요.


Giljae Joo

unread,
May 23, 2011, 10:22:11 PM5/23/11
to ks...@googlegroups.com
저같은 경우는, core부분은 nhn에서 만든 lucy-xss를 사용했습니다.
서블릿 필터나 인터셉터를 이용해서 처리하시면 될듯 합니다.
--
Giljae Joo(주길재),
twitter. @giljae
//Stay hungry, stay foolish - Steve Jobs//

2011. 5. 24., 오전 11:01, StyLe_jG 작성:

선영욱

unread,
May 23, 2011, 10:29:44 PM5/23/11
to ks...@googlegroups.com
아~제가 만든 방식이 블랙 리스트 방식이로 lucy-xss은 화이트 리스트 방식이군요.
 
저는 고객사에서 파악한 블랙 리스트를 활용해 달라는 말때문에 그 방식을 선택했는데, 앞으론 lucy-xss 처럼 화이트 리스트 방식으로 처리해야 겠습니다.
 
좋은 방법 알려주셔서 감사합니다 ^^

2011년 5월 24일 오전 11:22, Giljae Joo <gil...@gmail.com>님의 말:

StyLe_jG

unread,
May 24, 2011, 9:05:53 PM5/24/11
to Korea Spring User Group
감사합니다. lucy-xss라는게 있군요.

저도 인터셉터랑 lucy-xss를 함께 써봐야겠네요.

감사합니다~^^

Sanghyuk Jung

unread,
May 24, 2011, 9:34:57 PM5/24/11
to ks...@googlegroups.com
Lucy-xss filter는 아래 pdf파일의 43페이지의 기사에 그 배경이 설명되어 있습니다.
 
 
NHN에서 여러 보안 이슈를 해결한 노하우가 녹아 있어서 다른 분들에게도 도움이 될거 같습니다.
 
그리고 오늘 아침에 이 쓰레드에 답글을 달려고 했는데, 비슷한 글을 찾다가 다른 글밑에 답글을 달았네요;
이 쓰레드에도 추가합니다.
"
참고로 덧붙이자면

request.getParameter()로 받은 값만 검사하면 하나의 이름으로 여러개의 값이 들어간 파라미터들은 지나치게 됩니다.

한 화면에서 같은 파라미터이름으로 다수 목록을 입력하는 변수도 XSS검증을 해야한다면 request.getParameterMap으로 받은 변수값을 검사하시는 편이 좋습니다.

request.getParameterMap으로 Map을 받으면 <String,String[]>의 형이 return되어서 여러개의 값이 들어간 변수의 값도 똑같이 참조됩니다. 값이 하나인 경우는 크기가 1인 String[]이 들어가게 되지요.

 이런식의 코드가 되겠죠.

@SupressWarnings(“unchecked”)
Map<String,String[]> params = request.getParameterMap();

for(String[] values : params.values()){
  for(String input : values){
   검사
  }
}
"
2011년 5월 25일 오전 10:05, StyLe_jG <cresp...@gmail.com>님의 말:

"손권남(KwonNam Son)"

unread,
May 30, 2011, 10:18:25 PM5/30/11
to ks...@googlegroups.com
참고로 XSS 필터는 무조건 White List 방식을 써야합니다.

XSS를 블랙리스트로 할 경우 나중에 브라우저에 추가되는 버그에 대응할 수
없기 때문입니다.

게다가 요즘엔 브라우저 종류도 너무 다양하죠.

White List 방식으로 해서 안전성이 검증된 태그와 속성, 속성값만을 받아들
여야 합니다.

2011년 05월 24일 11:29, 선영욱 쓴 글:


> 아~제가 만든 방식이 블랙 리스트 방식이로 lucy-xss은 화이트 리스트 방식이
> 군요.
> 저는 고객사에서 파악한 블랙 리스트를 활용해 달라는 말때문에 그 방식을 선
> 택했는데, 앞으론 lucy-xss 처럼 화이트 리스트 방식으로 처리해야 겠습니다.
> 좋은 방법 알려주셔서 감사합니다 ^^
>
> 2011년 5월 24일 오전 11:22, Giljae Joo <gil...@gmail.com

> <mailto:gil...@gmail.com>>님의 말:


>
> 저같은 경우는, core부분은 nhn에서 만든 lucy-xss를 사용했습니다.
> 서블릿 필터나 인터셉터를 이용해서 처리하시면 될듯 합니다.
> --
> Giljae Joo(주길재),
> twitter. @giljae
> //Stay hungry, stay foolish - Steve Jobs//
>
> 2011. 5. 24., 오전 11:01, StyLe_jG 작성:
>
> > 초보 개발자 입니다.
> >
> > 이번에 스프링을 통한 프로젝트를 진행하고 있는데요, XSS 처리를 어
> 떻게 할지 고민이 되어 글을 올립니다.
> >
> > 기존의 다른 프로젝트에서는 HttpServletRequest 의 파라미터 들을 가
> 로채서 <, > 같은 것들을 치환해 주면서 처리
> > 했는데요.
> >
> > 스프링에서 더 좋은 방법, 혹은 노하우가 있으시면 공유 부탁 드립니다.
> >
> > 그리고, 혹시 스프링 인터셉터를 통해 컨트롤러로 들어오는 모든 파라
> 미터를 가로채서 처리하는 방법으로 XSS를 처리하면 문제가 없
> > 을지, 이렇게 적용해보신 분들의 답변 기다리겠습니다.
> >
> > 고수님의 손길을 기다립니다.ㅜㅜ
> >
> > --
> > Google 그룹스 'Korea Spring User Group' 그룹에 가입했으므로 본 메
> 일이 전송되었습니다.
> > 이 그룹에 게시하려면 ks...@googlegroups.com

> <mailto:ks...@googlegroups.com>(으)로 이메일을 보내세요.
> > 그룹에서 탈퇴하려면 ksug+uns...@googlegroups.com
> <mailto:ksug%2Bunsu...@googlegroups.com>로 이메일을 보내주세요.


> > 더 많은 옵션을 보려면 http://groups.google.com/group/ksug?hl=ko
> 서 그룹을 방문하세요.
> >
>
> --
> Google 그룹스 'Korea Spring User Group' 그룹에 가입했으므로 본 메일
> 이 전송되었습니다.
> 이 그룹에 게시하려면 ks...@googlegroups.com

> <mailto:ks...@googlegroups.com>(으)로 이메일을 보내세요.
> 그룹에서 탈퇴하려면 ksug+uns...@googlegroups.com
> <mailto:ksug%2Bunsu...@googlegroups.com>로 이메일을 보내주세요.

밤바

unread,
May 31, 2011, 1:25:48 AM5/31/11
to Korea Spring User Group

XSS는 입력 시 차단하는 방법과 출력 시 차단하는 방법이 있습니다.
많은 분들이 입력 시 차단하는 방법을 안내를 해주셔서 저는 출력 시 차단하는 방법을 안내해 드립니다.

[XSS: 출력 시 차단 전략]

출력시 차단하는 방법의 기본 사상은
XSS라는 것이 문제가 되는 근본적인 원인은 입력된 문자열이
HTML Tag로 해석되어 의도치 않은 동작을 유발하는 것이라는데 있습니다.
그리고 입력하는 값에 대해서는 실제로 입력자의 의도 상
HTML Tag가 들어갈 수도 있다는 것을 전제로 합니다. (게시판의 HTML 입력)

따라서 입력 패턴은 검사하지 않고 출력 시 무력화 시키는 것이 주요 골자인데
다름 아닌 왠만한 taglib에서 이미 이 기능이 구현되어 있습니다.

-------------------------------------------------------------------------------------------------

Apache Commons를 활용한 예
http://blog.naver.com/phrack?Redirect=Log&logNo=80086347596

Struts Taglib을 활용한 예
http://blog.naver.com/phrack?Redirect=Log&logNo=80053722854

Struts Response Utils를 활용 한 예
http://blog.naver.com/phrack?Redirect=Log&logNo=80053722954

JSTL을 활용한 예
http://blog.naver.com/phrack?Redirect=Log&logNo=80053722757

-------------------------------------------------------------------------------------------------

Spring을 사용할 때도 Spring Taglib을 사용하시면 default가 HTML Tag를 무력화 시켰던 것으로 기억합니
다.
간혹 Taglib 사용이 과도할 경우 화면 렌더링에 무리가 갈 수 있는데, 이 경우는 부분적으로 scriptlet으로 대체하여
보완할 수 있습니다.

이 방법은 아래오 같은 상황에서 활용하시면 유리합니다.

사용자 입력에 HTML Tag를 허용해야하는 경우
DB에 입력된 입력 값이 외부 인터페이스로 전달되는 경우 (예: 전문 통신)
입력한 값의 출력 채널이 Web Browser가 아닌 다양한 채널을 지원해야할 경우
Spring의 Controller가 아닌 JSP/Servlet 등이 혼재된 경우, 특정 JEE 구현 기술에 종속되지 말아야할 경
우 (JSTL 활용)
JSP 개발 표준에 Taglib 사용이 활성화된 경우
....

한 예로 모 금융 사이트에서 Filter 방식으로 XSS 패턴을 치환을 하였다가
해당 데이터를 활용하는 타 시스템에서 다시 치환된 패턴을 역치환하게 되었는데
외부 시스템이 늘어날 수록 역치환하는 모듈이 분산되어 모양새가 좋지 않게 나온 사례가 있습니다.
이런 경우 활용하시면 되겠습니다.

[XSS: 입력 시 차단 전략]


입력 시 차단하는 방식은 일정한 패턴을 리스트화하여 이에 대해 대응하는 방법입니다.
이 방법은 많은 보안 담당 부서에서 보안 심의 시, 리스트화된 패턴으로 테스트를 한다는데 착안한 대응 방법입니다.
XSS의 발생 원인 자체를 생각한다면 HTML Tag를 무력화 시키는 Taglib 사용이 맞습니다만
입력된 데이터가 출력되는 다양한 화면을 모두 통제하는 것이 어렵다고 판단할 경우 이 방법을 씁니다.

입력 시 차단 방식은 아래와 같은 경우 유용합니다.

많은 프로젝트에서 보안팀이 패턴 리스트를 확보한 상태에서 모의 해킹을 시도하는 경우
SQL Injection 처럼 그 패턴이 무궁무진하여 수시로 업데이트가 필요한 경우
입력된 값의 출력 채널이 Web Browser로 국한될 경우
...

한편, 입력 단계에서 차단하는 방식은 많은 분들이 권해 주셔서 첨언 할 것은 없을 것 같고
다만, 리스트 방식으로 관리를 하신다면 굳이 해당 모듈을 XSS에 국한시키실 필요가 없습니다.
패턴 리스트를 관리를 할 것이라면 XSS 차단 뿐만 아니라, 욕설 방지, SQL Injection 차단 등에도 활용이 가능하므

좀 더 범묭적인 이름으로 모듈을 구성하신 후, 원하는 위치에 꽂아 넣는 것을 권해드립니다.

마침 최근에 제가 SQL Injection 패턴 감지 및 치환 관련 모듈을 만들어둔 것이 있어 공유해 드립니다.
아직 보완 중이라 허점이 많긴 합니다만
ant와 같이 includes, excludes 패턴 정의가 가능하고 simple, regex, antstyle 패턴 검색, 치
환까지 (antstyle 치환은 미정) 구현체를 만들어 두었습니다.

참고: http://search.maven.org/#artifactdetails|org.codelabor|codelabor-system-pattern|3.0.3|jar


Spring Bean 형태로 되어 있어 원하는 위치에 꽂아 넣으실 수 있습니다.
참고로 저는 AOP 걸고 DB 접근 전에 SQL Injection 차단용으로 활용하고 있습니다.
(제 경우 입력 값이 화면에서만 들어온다는 보장이 없어 DB 입력 전에 차단)

Maven으로 작업해 둔 것이라 의존 관계가 좀 거슬릴 수 있습니다만 source, javadoc 있으니 참고는 가능할 것 같습
니다.
혹, 보시다가 보완이 필요하다거나 더 좋은 아이디어 있으시면 피드백 주시면 좋겠네요. ㅎㅎ

Reply all
Reply to author
Forward
0 new messages