[보안] 크로스사이트스크립팅 방지용 필터 - HTMLTagFilter

크로스사이트스크립팅이라는 사이트해킹기법은 사용자의 뷰에서 스크립트코드를 전송시켜 시스템을 해킹하는 방법을 말합니다.


<script> 로 시작하는 코드를 전송시켜 아래 해당 내용을 서버에서 실행시키는 방법이죠. HTML에서는 정규식이라는 방법으로 [<] 와 같은 기호들은 [ &lt; ] 와 같은 코드로 변환시켜 서블릿전송을 합니다.


그런데 호출되는 메서드에서 공통코드 변환 치환자를 대입하려면 작업이 만만치 않습니다. 따라서 필터를 사용해서 .do 를 호출하는 경우 강제로 필터를 거치게 만들어 빠르고 쉽게 크로스사이트스크립팅 방지를 할 수 있습니다.


전자정부프레임워크에서는 이러한 정규식처리를 보다 쉽고 편하게 처리하기 위해 HTMLTagFilter 클래스를 구현하여 정규식변환처리를 하고 있어서 프로젝트 개발시 참고하기에 좋기에 소개를 해 드립니다.


필터를 사용하기 위해서는 web.xml에 필터선언 부분을 추가합니다.


web.xml

    <filter>
        <filter-name>HTMLTagFilter</filter-name>
        <filter-class>infrastructure.web.servlet.filter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>HTMLTagFilter</filter-name>
        <url-pattern>*.do</url-pattern>
    </filter-mapping>   


.do 로 호출되는 모든 URL은 필터를 거치게 되며 필터에서 정규식변환처리가 일어납니다. infrastructure.web.servlet.filter 는 현재 구성된 필터의 위치이며 사용하시는 패키지위치에 맞춰서 바꿔주셔야 됩니다.



HTMLTagFilter.java

/*
 * Copyright 2008-2009 MOPAS(MINISTRY OF SECURITY AND PUBLIC ADMINISTRATION).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package infrastructure.web.servlet.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

public class HTMLTagFilter implements Filter{

	private FilterConfig config;

	@Override
	public void destroy() {

	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {

		chain.doFilter(new HTMLTagFilterRequestWrapper((HttpServletRequest)request), response);
	}

	@Override
	public void init(FilterConfig config) throws ServletException {
		this.config = config;
	}
}

 


HTMLTagFiler에서는 HTMLTagFilterRequestWrapper 객체를 호출해서 사용하고 있는 구현 클래스입니다.


HTMLTagFilterRequestWrapper.java

/*
 * Copyright 2008-2009 MOPAS(MINISTRY OF SECURITY AND PUBLIC ADMINISTRATION).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package infrastructure.web.servlet.filter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

public class HTMLTagFilterRequestWrapper extends HttpServletRequestWrapper {

	public HTMLTagFilterRequestWrapper(HttpServletRequest request) {
		super(request);
	}

	@Override
	public String getParameter(String parameter) {

		String value = super.getParameter(parameter);

		if(value==null){
			return null;
		}

		StringBuffer strBuff = new StringBuffer();

		for (int i = 0; i < value.length(); i++) {
			char c = value.charAt(i);
			switch (c) {
			case '<':
				strBuff.append("<");
				break;
			case '>':
				strBuff.append(">");
				break;
			case '&':
				strBuff.append("&");
				break;
			case '"':
				strBuff.append(""");
				break;
			case '\'':
				strBuff.append("'");
				break;
			default:
				strBuff.append(c);
				break;
			}
		}

		value = strBuff.toString();

		return value;
	}

	@Override
	public String[] getParameterValues(String parameter) {

		String[] values = super.getParameterValues(parameter);

		if(values==null){
			return null;
		}

		for (int i = 0; i < values.length; i++) {
			if (values[i] != null) {
				StringBuffer strBuff = new StringBuffer();
				for (int j = 0; j < values[i].length(); j++) {
					char c = values[i].charAt(j);
					switch (c) {
					case '<':
						strBuff.append("<");
						break;
					case '>':
						strBuff.append(">");
						break;
					case '&':
						strBuff.append("&");
						break;
					case '"':
						strBuff.append(""");
						break;
					case '\'':
						strBuff.append("'");
						break;
					default:
						strBuff.append(c);
						break;
					}
				}
				values[i] = strBuff.toString();
			} else {
				values[i] = null;
			}
		}

		return values;
	}

}

 


실제적으로 정규식변환처리를 하는 클래스입니다.


이렇게 web.xml과 필터클래스 두개만 추가하면 아주쉽게 크로스크로스스크립팅을 방지할 수 있습니다.


혹시 정규식 변환에 문제가 생기면(URL 파라미터값에 특수문자가 꼭 필요한경우) 해당 메서드만 예외처리를 하는 방법도 있겠네요.


첨부파일 다운 :  HTMLTagFilter.zip