목차

JSP 보안 개발 가이드

1절. 보안 대책

1. 스크립트 삽입 취약점

가. 취약점 상세 내용 및 보안 대책

Javascript, Vbscript 등 PC의 웹브라우저에서 실행되는 클라이언트 사이트 스크립트를 다른 사용자의 웹브라우저에서 실행하도록 함으로서 웹 브라우저를 제어하여 PC를 공격하는 취약점을 말한다. 공격에 사용되는 유형은 크게 두가지로 분류할 수 있다.

(1) Reflected XSS

이 유형의 XSS는 클라이언트 측에서 전송된 데이터가 서버측에서 즉시 처리된 후 사용자에게 응답으로 전송되는 돌아오는 경우에 해당한다. 다음과 같은 상황에서 발생이 가능하다.

  1. 검색 페이지에서 입력된 검색어가 검색 결과 페이지에 표시되는 경우
  2. URL에 포함된 특정 파라미터가 응답 페이지에 hidden 속성으로 포함되어 있는 경우

위의 두가지 유형은 본질적으로는 동일한 내용이다.
이러한 유형의 XSS 는 사회 공학적 방법 등을 통해서 공격 스크립트가 포함된 URL을 타인이 실행하도록 유도함으로서 (예를 들면 메신저로 링크를 전송하거나, 게시판에 URL을 링크로 걸어놓고 클릭을 유도하는 방식 등) 공격에 이용될 수 있다. 다만, 공격자가 강제적으로 타 사용자의 PC에서 공격 스크립트가 실행되도록 할 수는 없으므로 일반적으로 심각한 취약점으로 분류되지는 않는다.
그러나 공공기관이나 금융권과 같이 신뢰도가 중요한 대상인 경우에는 이 유형의 XSS 도 모두 제거해야 하며, 그 외에도 대외에 공개된 웹사이트라면 일반적으로 제거하도록 하는 것이 좋다.

(2) Stored XSS

게시판과 같이 사용자가 입력한 정보가 서버측 DB에 저장되어 있다가 타 사용자가 해당 정보를 열람할 때 DB에 저장되어 있는 정보를 가져와 화면에 출력하는 방식의 웹 애플리케이션에서 발생하는 취약점으로서, XSS의 가장 핵심적인 취약점이라고 할 수 있다. 불특정 다수를 대상으로 열람자의 웹브라우저에서 공격 스크립트를 실행할 수 있기 때문에 심각한 위협이 발생한다.
공격자가 XSS를 목적으로 악성 스크립트를 삽입하여 둘 수 있는 위치는 비단 게시판의 글 본문 뿐만 아니라 제목, 작성자 이름, 날짜, 첨부파일 이름 등이 모두 가능하며, 또한 게시판 외에도 사용자 프로필의 닉네임, 주소, 전화번호, 등 사용자가 입력이 가능한 모든 데이터에 스크립트가 삽입될 수 있다.

나. 보안 대책

XSS에 대한 보안 대책은 적용할 대상에 따라 다음의 두가지 경우를 나누어 적용해야 한다. 먼저 태그를 사용할 필요가 없는 경우와 태그의 사용을 허용해야 하는 경우이다.

(1) 태그를 허용할 필요가 없는 경우 (사내 게시판, Reflected XSS)

태그를 허용할 필요가 없는 사내 게시판 등 단순 게시판의 경우는 사용자가 입력하는 모든 데이터에서 <, > 문자를 HTML Special Character 로 인코딩 함으로서 XSS를 완전히 차단할 수 있다. HTML Special Character 로 인코딩 된 코드는 웹브라우저에서 화면에 출력될 때는 정상적인 문자열로 출력되지만, 태그나 스크립트로서는 작동하지 않기때문에 XSS 로부터 안전하게 된다.

인코딩 대상 문자 HTML Special Character 코드
< &lt;
> &gt;


Reflected XSS 는 화면에 표시되는 모든 변수값들 (hidden field 포함)에 대해서 발생 가능하므로 모든 출력값에 대한 검증이 수행되어야 한다.

JSP

따로 제공하는 인코딩 함수가 없으므로 직접 replace 문을 통해 <, > 를 필터링하는 함수를 작성하여 사용한다.

resultStr = resultStr.replaceAll("<", "&lt;");
resultStr = resultStr.replaceAll(">", "&gt;");

한편, jsp 에서는 프리젠테이션 페이지를 작성할 때, JSTL 을 사용하면 모든 출력값이 자동으로 인코딩되므로 따로 replace를 할 필요가 없으므로 편리할 수 있다. (개발 단계라면 권고할 만 함)

<c:out value="${value}" />
(2) 태그를 허용해야 하는 경우 (공개 게시판)
게시판의 태그 허용에 대한 대응

공개 게시판과 같은 커뮤니케이션 중심의 웹 애플리케이션에서는 사용자들이 게시물을 꾸미거나 링크, 이미지, 동영상 등의 사용을 원하기 때문에 HTML 태그를 완전히 금지할 수 없다. 따라서 <, >를 필터링하되, 사용자가 사용해야하는 태그에 대해서는 <, > 를 필터링해서는 안된다.
따라서 웹사이트 운영자는 자신의 게시판에서 사용자에게 허가할 최소한의 HTML 태그를 선별한 후, 각각의 태그들에 대해서만 역변환 (즉, &lt;, &gt; 등으로 replace 된 <, >를 다시 원래대로 되돌리는 것)해야 한다.
또한 해당 태그들을 허용할 경우 발생 가능한 위협들에 대해서 대처하기 위한 별도의 방어 코드를 추가로 작성해야 한다. 방어 코드는 다음의 두 가지 방식을 적용할 수 있다.

가. 단어 blacklist 를 필터링 하는 방식

이 방식은 XSS 공격에 자주 사용되는 단어를 필터링하여 사용할 수 없도록 하는 방식이다
이 방식은 구현하기가 간단하지만, blacklist에 포함되지 않는 코드가 공격에 사용될 경우 막을 수 없으며, 또한 필터링 우회 기법이 발전함에 따라 필터링 자체가 우회될 가능성이 있다. 또한 blacklist로 선정된 단어를 사용자가 게시물에 사용할 수 없다는 단점이 있다.

blacklist 코드 예
// blacklist 를 필터링하여 사용할 수 없도록 함
test_str_low= test_str.toLowerCase();
test_str = test_str_low;
test_str = test_str.replaceAll("javascript", "x-javascript");
test_str = test_str.replaceAll("script", "x-script");
test_str = test_str.replaceAll("iframe", "x-iframe");
test_str = test_str.replaceAll("document", "x-document");
test_str = test_str.replaceAll("vbscript", "x-vbscript");
test_str = test_str.replaceAll("applet", "x-applet");
test_str = test_str.replaceAll("embed", "x-embed");  // embed 태그를 사용하지 않을 경우만
test_str = test_str.replaceAll("object", "x-object");    // object 태그를 사용하지 않을 경우만
test_str = test_str.replaceAll("frame", "x-frame");
test_str = test_str.replaceAll("grameset", "x-grameset");
test_str = test_str.replaceAll("layer", "x-layer");
test_str = test_str.replaceAll("bgsound", "x-bgsound");
test_str = test_str.replaceAll("alert", "x-alert");
test_str = test_str.replaceAll("onblur", "x-onblur");
test_str = test_str.replaceAll("onchange", "x-onchange");
test_str = test_str.replaceAll("onclick", "x-onclick");
test_str = test_str.replaceAll("ondblclick","x-ondblclick");
test_str = test_str.replaceAll("enerror", "x-enerror");
test_str = test_str.replaceAll("onfocus", "x-onfocus");
test_str = test_str.replaceAll("onload", "x-onload");
test_str = test_str.replaceAll("onmouse", "x-onmouse");
test_str = test_str.replaceAll("onscroll", "x-onscroll");
test_str = test_str.replaceAll("onsubmit", "x-onsubmit");
test_str = test_str.replaceAll("onunload", "x-onunload");
}
나. 태그의 property를 검증하는 방식

사용을 허가할 각각의 태그들에 대해서 property 들에 대해 개별적으로 유효성 검사를 실시하여 정상적이지 않은 방식으로 사용된 property를 걸러내는 방식이다. 이 방식은 구현하기가 좀더 복잡하지만 허가되지 않은 모든 형태의 입력을 거부하는 방식이므로 우회될 가능성이 낮아 보다 안전하며, 필터링이 사용자의 게시물의 내용을 손상시키지 않는 장점이 있다.
예를 들면 <img> 태그에 대해 다음과 같은 규칙을 적용하여 규칙이 위반된 property는 모두 삭제하는 방식이다.

img 태그의 허가 규칙
- img 태그는 property에 src, width, height 만 허용(그 외의 모든 property 는 무시)
- src 는 http://- 로 시작하는 이미지 파일 경로만 허용 (확장자로 . jpg .gif 등만 허용)
- width, height 의 값은 숫자만 허용

이 방식의 대책을 적용하기 위해서 고려해야 할 요소들은 다음과 같다.

새로운 HTML 규약의 개발, 웹브라우저의 발전 등으로 인해 XSS 공격 패턴은 계속 새로운 패턴이 개발될 것이기 때문에, XSS 에 대한 필터링 로직 역시 지속적으로 테스트되고 수정되어야 할 필요가 있다.

2. SQL Injection 취약점

가. 취약점 상세 내용 및 보안 대책

웹 사이트는 DBMS와 연동하므로 웹 어플리케이션에서 사용자의 입력값을 통하여 데이타 트랜잭션이 발생함. 만일 사용자 입력값에 대한 유효성 검증이 누락될 경우, 악의적인 사용자는 정상적인 입력값 대신 SQL 쿼리문이 포함된 조작된 입력값을 전송하여 서버측 쿼리문의 구조를 변경할 수 있으며, 이를 통해서 사용자 인증을 우회하거나 데이터베이스의 정보를 유출시키고 서버의 시스템 명령어를 실행시킬 수도 있음.

나. 보안 대책

(1) Database 운영 레벨에서 SQL Injection 방어 대책

DB 또는 웹사이트 운영자가 SQL Injection을 방어하기 위해서는 기본적으로 다음과 같은 사항에 유의하여 관리가 필요하다.

그러나 위와 같은 방법만으로는 SQL Injection을 방어할 수 없으므로 다음과 같이 소스코드 레벨에서 취약점을 제거하기 위한 대책을 적용해야 한다.

(2) 소스코드 레벨에서 Prepared Statement 구문을 통한 SQL Injection 방어

웹사이트가 개발중에 있다면 DAO 객체 또는 DB 연결 구문에서 Prepared Statement 구문을 이용하여 DB 트랜잭션을 처리함으로서 SQL Injection 취약점이 근본적으로 발생하지 않는 구조로 웹사이트를 개발해야한다.
Prepared Statement 구문은 SQL 쿼리를 선처리하여 컴파일 한 후, 이후 입력되는 변수값을 항상 문자열 변수로 다루기 때문에 사용자가 어떤 악의적인 SQL 구문을 변수에 삽입해도 SQL 문에 영향을 미치지 않아 SQL Injection이 발생하지 않는다.

JSP 에서 Prepared Statement 구문 사용

Jsp 에서 prepared Statement 구문을 구성하는 간단한 예시는 다음과 같다.

prepared Statement 구문
// 객체 선언
Connection con;
PreparedStatement pstmt;
ResultSet rs;

// DB연결 생성
con = DriverManager.getConnection(-------);

// Query 문 및 변수값 세팅
pstmt = con.prepareStatement(“Select  name, id, num from Membertable where id=? And passwd=?“);
pstmt.setString(1, "test");             // 변수형에 따라 setXXXX 사용 ex) setInt, setDouble
pstmt.setString(2, "testpwd");

// Query 문 실행
rs = pstmt.executeQuery();          // executeQuery, executeUpdate

// 결과 처리
if (rs.next()){
	// rs 객체로부터 칼럼 이름을 이용한 결과값 추출하여 사용자 펑션의 실행
	Run_user_function (…, rs.getString(name), rs.getString(id), rs.getint(num));
	// 또는 인덱스를 이용한 결과값 추출
	Run_user_function (…, rs.getString(1), rs.getString(2), rs.getint(3));

}

// 객체 close
rs.close();
pstmt.close();

※ 참고 : 저장 프로시저를 이용하여 DB 트랜잭션을 처리하는 방법 역시 prepared statement 구문과 동일한 효과를 기대할 수 있다.

(3) 소스코드 레벨에서 필터링 코드를 통한 SQL Injection 방어

만일 이미 운영중인 웹사이트에서 DB 트랜잭션 처리를 Prepared Statement 구문으로 수정하는 것이 어려울 경우, 차선책으로 특수 문자 및 Query 문자열에 대한 필터링을 통해서 SQL Injection 이 발생하지 않도록 해야 한다.
사용자측으로부터 전달되는 파라메터 중 DB 쿼리문에 사용되는 모든 파라미터 (게시판 ID, 글 번호, 검색 keyword, 사용자 번호, 항목 번호, 분류명칭 등)로부터 입력되는 데이터에 대하여 아래와 같이 특수 문자 및 Query 예약어를 필터링해 에러 처리를 하거나 ‘\’ 문자 또는 공백 문자로 치환한다.

필터링 할 특수 문자 및 구문
' union
select
insert
# drop
( update
) from
; where
@ join
= substr (oracle)
* user_tables (oracle)
/ user_table_columns (oracle)
+ subsring (ms-sql)
information_schema (mysql) sysobjects (ms-sql)
table_schema (mysql) declare (ms-sql)
JSP 에서 필터링 샘플 코드
필터링 샘플 코드
// 특수문자 필터링을 위해 특수문자를 정의
Pattern evilChars = Pattern.compile("['\"\\-#()@;=*/+]");
// 특수문자는 모드 공백으로 치환
test_str = evilChars.matcher(test_str).replaceAll("");

// 특수 구문 필터링 (데이터베이스가 Oracle 인 경우)
test_str_low= test_str.toLowerCase();
if(test_str_low.contains("union") || test_str_low.contains("select") || test_str_low.contains("insert") || test_str_low.contains("drop") || test_str_low.contains("update") || test_str_low.contains("delete") || test_str_low.contains("join") || test_str_low.contains("from") || test_str_low.contains("where") || test_str_low.contains("substr") || test_str_low.contains("user_tables") || test_str_low.contains("user_tab_columns"))
{
test_str = test_str_low;
test_str = test_str.replaceAll("union", "q-union");
test_str = test_str.replaceAll("select", "q-select");
test_str = test_str.replaceAll("insert", "q-insert");
test_str = test_str.replaceAll("drop", "q-drop");
test_str = test_str.replaceAll("update", "q-update");
test_str = test_str.replaceAll("delete", "q-delete");
test_str = test_str.replaceAll("and", "q-and");
test_str = test_str.replaceAll("or", "q-or");
test_str = test_str.replaceAll("join", "q-join");
test_str = test_str.replaceAll("substr", "q-substr");
test_str = test_str.replaceAll("from", "q-from");
test_str = test_str.replaceAll("where", "q-where");
test_str = test_str.replaceAll("declare", "q-declare");
test_str = test_str.replaceAll("openrowset", "q-openrowset");
test_str = test_str.replaceAll("user_tables","q-user_tables");
test_str = test_str.replaceAll("user_tab_columns","q-user_tab_columns");
test_str = test_str.replaceAll("table_name","q-table_name");
test_str = test_str.replaceAll("column_name","q-column_name");
test_str = test_str.replaceAll("row_num","q-row_num");
}

3. 파일 업로드

가. 취약점 상세 내용 및 보안 대책

첨부 파일 업로드 기능이 있는 게시판 등에서 실행 가능한 확장자를 가진 스크립트 파일의 업로드가 허용되는 경우, 공격자에 의해 악성 프로그램이 업로드 되어 실행 될 수 있음.
공격자는 첨부한 악성 프로그램을 실행하여 웹 서버 사용자 권한 획득한 후 내부 네트워크로의 침입을 시도하거나 DB 에 연결하여 중요 정보를 유출시킬 수 있음.

나. 보안 대책

(1) 서버 운영 관점의 보안 대책

서버 운영 관점에서 아래와 같은 대책을 적용함으로서 소스코드 상의 취약점에 의해서 악성 파일이 업로드 되더라도 공격자가 이를 실행할 수 없도록 함으로서 업로드 취약점에 의한 피해를 최소화 해야 한다.

(2) 소스코드 관점의 보안 대책

웹 애플리케이션의 소스코드에서 아래와 같이 실행 가능한 파일들이 서버에 업로드 할 수 없도록 필터링하여 제한하는 모듈을 추가해야 한다.

ASP .asa, .asp, .cdx, .cer, .htr, .aspx
JSP .jsp, .jspx
PHP .html, .htm, .php, .php3, .php4, .php5

위의 표에서 제시된 확장자 목록들은 일반적인 설정 환경에 해당되는 목록이지만, 각 서버측 스크립트 엔진에서 실행 가능한 것으로 인식하는 확장자의 종류는 각각의 서버측 설정에 따라 다르다. 따라서 만일 별도로 등록한 실행 가능 확장자가 있다면 제한 목록에 추가해야 한다.
한편, 실제로 필터링 로직을 구현할 때, black list 방식의 필터링 (제한할 목록 외에는 모두 허용하는 방식) 으로 구현할 경우, 제한할 keyword의 누락 가능성이 존재하고 또한 문자열 인코딩 등을 통해서 필터링의 우회가 가능할 수 있기 때문에 일반적으로 더 안전한 white list 방식의 필터링이 권장된다.
white list 방식의 필터링은 허용할 확장자 목록(예: .jpg, .doc, .xls 등) 만을 확정 선정하고 그 외의 모든 확장자를 제한하는 방식의 필터링이다.

확장자 필터링 로직은 일반적으로 다음과 같은 원칙에 따라 구현되어야 한다.

위에서 마지막 두가지 적용 항목은 구현시 복잡한 로직의 변경이 요구되므로 이미 운영되고 있는 서버의 경우 필수적인 항목은 아니다. 그러나 금융권과 같이 완벽한 보안을 추구해야만 하는 곳이거나 개발 단계에서 보안이 고려되는 경우는 위의 두가지 로직을 적용하도록 권고해야 한다.

JSP 에서 소스 코드 보안 대책
파일 확장자 추출 코드 예시
<%
   String filePath = "/test/test.jsp";
String fileExt = filePath.substring(filePath.lastIndexOf('.') + 1).toLowerCase();
%>
Black List 방식의 필터링 코드 예시
<%

Boolean checkResult = true;

// 업로드 금지 확장자 리스트
String blockExt[] = {"jsp","jspx"};

// 금지할 확장자 체크
for(int i=0; i<blockExt.length;i++) {
if( blockExt[i].equals(fileExt) ){
checkResult = false;
break;
    }
}

// Windows일 경우 (.) 및 세미콜론 파싱 오류 관련 처리
if(fileExt.length() == 0 ) {
checkResult = false;
}
if(filePath.contains(";")) {
checkResult = false;
}

if(checkResult == false){
out.println ("업로드가 금지된 파일 입니다.");
}else{
out.println ("업로드가 허용된 파일 입니다.");
}

%>
White List 방식 필터링 코드 예시
<%

Boolean checkResult = false;

// 업로드 허용 확장자 리스트
String allowExt[] = {"doc","docx","xls","xlsx","jpg","gif","txt"};

// 허용할 확장자 체크
for(int i=0; i<allowExt.length;i++) {
if( allowExt[i].equals(fileExt) ){
checkResult = true;
break;
    }
}

// Windows일 경우 세미콜론 파싱 오류 관련 처리
if(filePath.contains(";")) {
checkResult = false;
}

if(checkResult == false){
out.println ("업로드가 금지된 파일 입니다.");
}else{
out.println ("업로드가 허용된 파일 입니다.");
}

4. 파일 다운로드

가. 취약점 상세 내용 및 보안 대책

Web Application 의 download 관련 모듈의 파라미터에 path traversal 문자열을 삽입하여 웹 루트 디렉토리의 상위 경로에 위치하는 OS파일 시스템까지 접근할 수 있으며, 이를 이용해서 시스템의 각종 중요 파일 및 웹 프로그램의 소스 코드를 다운로드할 수 있음.

나. 보안 대책

파일 다운로드 취약점으로부터 안전하기 위해서는 다운로드 모듈을 다음과 같이 구현하도록 일반적으로 권고된다.

그러나 위의 방식으로 구현하기 위해서는 웹사이트 로직을 수정하는 데 다소 복잡한 작업이 필요하다. 따라서 공공기관이나 은행권 사이트와 같이 정보 노출에 매우 민감한 사이트를 제외한 내부 직원용 포털 등의 사이트에서는 차선책으로서 다음과 같은 필터링 코드를 적용하여 취약점을 해결하도록 한다.

JSP 에서 필터링 코드의 구현 예시
필터링 코드의 구현 예시
<%
// 다운로드 허용할 디렉토리 설정
String allowPath = "/server/upfiles/";

// 파라미터로부터 다운로드할 파일을 입력 받아 전체 경로를 생성함
String inputPath = getParameter("downfile");
String filePath = allowPath + inputPath;

// 금지 문자열 리스트
String blockchar[] = {"..", "../", "..\\"};

Boolean checkResult = true;

// 금지할 문자열 포함 여부 체크
for(int i=0; i<blockchar.length;i++) {
if( filePath.indexOf(blockchar[i]) != -1 ){
checkResult = false;
}
}

// 파일 전체 경로로부터 디렉토리 경로만 추출한 후, 다운로드 허용된 디렉토리인지 체크
String path = filePath.substring (0, filePath.lastIndexOf("/") + 1).toLowerCase();
if( !path.equals(allowPath) ){
    checkResult = false;
   }

if(checkResult == false){
out.println ("다운로드가 금지된 파일 입니다.");
}else{
out.println ("다운로드가 허용된 파일 입니다.");
}

%>

5. URL 강제 접속 / 인증 우회

가. 취약점 상세 내용 및 보안 대책

모든 웹페이지는 개별적으로 인증 및 권한 관리 모듈을 포함하고 있어야 한다. 그렇지 않을 경우 인증받지 않은 사용자가 해당 페이지의 URL 을 직접 입력하여 강제 접속할 수 있다.
또한 인증 및 권한 모듈은 반드시 안전한 방식으로 구현되어야 하며, 만일 인증 및 권한 관리 로직이 취약하여 우회가 가능하거나 권한 관리가 제대로 이루어지지 않는 경우, 불법적인 접근이나 허가받지 않은 Role 의 허용으로 중요 정보의 유출, 서비스의 무단 사용 등 심각한 문제가 발생할 수 있다.

나. 보안 대책

URL 강제 접속 또는 인증 우회 취약점은 웹사이트의 인증 및 권한 관리 모듈의 취약점으로 인해 발생하게 된다.
이를 해결하기 위해서는 웹사이트의 모든 페이지에 대해서 개별적으로 적절한 인증 및 권한 검증이 수행되어야 하므로 일반적으로 인증 및 권한 관리를 담당하는 공통 모듈을 작성하여 각 페이지에 삽입하는 방식으로 구현하는 경우가 많다.
인증 및 권한 관리 모듈에서 발생하는 취약점의 주요 원인은 다음과 같다.

(1) 특정 페이지에 인증 및 권한 관리 모듈이 누락된 경우

인증 및 권한 관리 모듈이 이미 존재하지만 특정 페이지에만 해당 모듈의 적용이 누락된 경우는 공통 모듈을 페이지에 추가하는 것으로 해결할 수 있다.
그러나 이러한 유형의 취약점은 여러 페이지에서 복수로 발견되는 경우가 일반적이기 때문에 취약점 진단(또는 모의해킹)에서 모든 페이지에 대한 전수 검사를 진행하지 않은 이상은 공통 인증 모듈이 누락된 페이지들 중에서 아직 발견되지 않은 경우가 존재할 가능성이 높다.
따라서 웹사이트 운영자 담당자 또는 유지보수 개발사는 이 취약점을 해결할 때 취약점이 보고된 특정 위치 뿐만 아니라 웹사이트의 모든 페이지에 대해서 검토를 실시할 것을 권고한다. 각각의 페이지에 대해서 다음 사항을 검토하도록 한다.

(2) 인증 및 권한 관리 모듈에 취약점이 발생하여 우회가 가능한 경우

인증 및 권한 관리 모듈의 취약점은 각 사이트마다 다양한 형태가 나타나지만 일반적으로 다음과 같은 사항들에 유의하여 모듈을 설계 및 수정함으로서 취약점을 보완하도록 한다.

가. 취약점 상세 내용 및 보안 대책

Cookie는 HTTP 프로토콜의 비연결성 특징을 고려하여 사용자 Session 관리의 편의성을 도모하기 위해 사용되는 기술적 방법이며, 주로 웹사이트의 설정값을 저장하여 각 사용자가 웹사이트에 접속할 때 동일한 설정을 유지하거나 또는 사용자의 인증과 관련된 정보를 처리하기 위해 사용된다.
그러나 Cookie 근본적으로 Client Side Session 기술로서 전달되는 값에 대한 사용자의 조작이 가능한 문제가 있기 때문에 Cookie 의 변수에 중요한 정보를 포함하여 사용하는 경우 Client 측 웹브라우저의 조작을 통해서 해당 값을 변조하여 인증을 우회하거나 타 사용자의 정보를 도용하는 등의 취약점이 발생할 수 있다.
또한 Cookie 로 전달되는 변수는 GET / POST 를 통해서 전달되는 변수와 동일하게 SQL Injection 및 파라미터 조작 등의 공격에 영향을 받을 수 있다.

나. 보안 대책

(1) Session 방식의 사용

평문 정보를 Cookie 변수에 저장하여 서버와 클라이언트 간에 전달하는 일반적인 방식의 Cookie 활용은 더 이상 권장되지 않는다.
WAS와 같은 서버측 스크립트 엔진은 Cookie 보다 발전된 형태인 Session 방식의 상태값 전달 방식을 지원한다. Session 방식은 서버측의 저장 공간에 각 사용자별로 인증 정보나 설정값 등 특화된 정보를 저장할 수 있는 저장소를 지원하며 암호화된 Cookie 변수를 통해 이를 식별하게 하는 방식으로 이루어져 있으므로 Client 측에서 정보의 변조가 불가능하며, 따라서 Cookie 방식보다 안전하다.
따라서 인증이나 권한 정보와 같이 변조되어서는 안되는 중요한 정보는 가능한 Session 방식을 이용하여 구현하는 것이 바람직하다.

만일 Cookie 변수에 데이터를 저장하여 전송할 필요가 있는 경우, 해당 정보가 인증 및 권한 등 중요한 정보일 경우 평문으로 사용해서는 안되며 반드시 SEED, 3DES, AES등 공인된 암호화 알고리즘을 사용하여 정보를 암호화한 후 사용해야 한다.
또한, 중요한 정보가 아니라고 해도, Cookie 변수를 통해서 전달되는 변수값은 GET/POST 파라미터 변수와 마찬가지로 SQL Injection, XSS, 파라미터 조작 등과 같은 공격에 영향을 받기 때문에 각각의 취약점을 방어하기 위한 적절한 입력값 검증이 수행되어야 한다.

7. URL 파라미터 조작

가. 취약점 상세 내용 및 보안 대책

공격자는 웹 URL의 GET/POST 파리미터 또는 HTML 코드의 <INPUT> 변수, Hidden field, javascript 변수 등에서 노출되는 데이터를 통해서 서버측 프로그램의 로직 및 역할 등을 유추할 수 있다. 또한 해당 변수의 값을 고의적을 변조하여 특정한 값을 입력하여 전송하므로서 서버측 프로그램이 자신이 원하는 특정 작업을 수행하도록 조작을 시도할 수 있다.
만일 웹사이트 로직이 신중하계 설계되지 않는다면 공격자가 전송한 조작된 입력값에 의해서 서버측 프로그램이 의도되지 않은 오동작이나 정상적인 처리 범위를 벗어난 불법적인 작업이 발생할 수 있다.
웹사이트의 유형이나 제공하는 기능에 따라서 파라미터 변조를 통해 발생할 수 있는 위협의 종류는 매우 다양하다. 일반적으로 발생 빈도가 높은 취약점 유형들을 정리하면 다음과 같다

나. 보안 대책

파라미터 변수의 변조를 통한 공격을 방어하기 위해서는 Client 측에서 전송되어온 정보가 변조되었을 가능성이 있다는 것을 항상 고려하여 서버측 프로그램을 설계해야 한다. 예를 들면 GET/POST 변수, Cookie변수, HTTP Header, Referer 등 Client 에서 전송되어 온 대부분의 데이터가 변조될 수 있다.
따라서 이와 같은 데이터 변조에 대비하기 위해서는 웹사이트에서 인증, 결재, 정보의 열람 및 수정 등 중요한 작업을 설계할 때 다음과 같은 사항에 유의하여 신중하게 로직을 설계해야 한다.

이 유형의 취약점은 진단 대상의 구조 및 종류, 서비스 유형 등에 따라서 다양한 형태로 발생하게 되므로 각 진단대상의 특성과 로직을 분석하여 대상에 맞는 적절한 보안 대책을 적용해야 한다.

8. 취약한 ID/PW

가. 취약점 상세 내용 및 보안 대책

로그인 인증을 통과해야만 접근할 수 있는 웹페이지의 경우, 취약한 계정을 사용한다면, 공격자는 해당 웹사이트의 정보를 바탕으로 자주 사용되는 word를 이용한 사전 파일 공격을 시도하거나, 또는 무작위 대입 방식에 의해서 취약한 계정을 획득할 수 있음.
시스템에서 기본으로 제공하는 계정이나 DBMS, 어플리케이션 서버 등에서 관리를 위해 제공하는 기본 계정을 그대로 사용하는 경우 공격자에게 쉽게 계정의 사용 여부가 노출될 수 있음. 일반 사용자 계정 역시 여러 가지 방법으로 공격자에게 계정의 존재 여부가 노출될 수 있음.

나. 보안 대책

사용자가 취약한 패스워드를 사용할 수 없도록 패스워드 생성 규칙을 선정하고 이에 대한 안내 및 강제할 수 있는 로직을 적용해야 함.

9. 디렉터리 인덱싱

가. 취약점 상세 내용 및 보안 대책

웹서버 설정상의 오류나 개발 과정의 편의를 위해서 웹 디렉토리 내부의 파일 리스트가 웹브라우져를 통해서 출력되도록 설정되어 있을 수 있음
웹 디렉토리의 파일 목록이 노출되면 공격자에게 웹사이트 구조 및 환경과 관련된 정보가 노출될 수 있으며, 백업 파일이나 설정 파일 등이 웹 디렉토리 내부에 존재할 경우, 공격자가 이 파일을 다운로드하여 웹사이트의 핵심적인 정보를 획득할 수 있음

나. 보안 대책

사용중인 웹서버를 확인한 후, 설정 파일 또는 관리 콘솔상에서 Directory Indexing 을 허용하지 않는 것으로 변경함.

<Directory “/usr/local/www”>
    Options Indexes FollowSymLinks     (---> Indexes 지시어 삭제)
    AllowOverride None
</Directroy>

*NODE
nex-edfa87d356c	WEBTOBDIR="C:/TmaxSoft/WebtoB4.1", 
		SHMKEY = 54000,
		DOCROOT="C:/TmaxSoft/WebtoB4.1/docs",
		PORT = "8080", 
		HTH = 1,
		LOGGING = "log1",
		ERRORLOG = "log2",
		JSVPORT = 9900,
		DirIndex = "diridx_full",
		Options = "-index"

*DIRINDEX
diridx_full	Options = "Fancy"

10. 디폴트 페이지

가. 취약점 상세 내용 및 보안 대책

웹서버, WAS 등 플랫폼을 디폴트 옵션으로 설치할 경우, 사용자의 편의를 위해 제공되는 각종 예제 및 샘플 페이지, 설치 정보, 관리 콘솔 등이 함께 설치된다. 이런 기능들은 제품별로 항상 동일한 경로에 설치되는 것이 일반적이며, 설치 정보가 일반에 공개되어 있기 때문에 공격자들의 주요 공격 목표가 될 수 있으며, 특히 샘플 페이지 등에 존재하는 취약점이 공격의 경로로 이용된 사례가 과거에 보고되어 있다.
따라서 샘플 페이지 등이 관리되지 않고 방치되는 경우 보안 취약점으로 작용할 가능성이 있는 만큼 사용하지 않는 기능은 설치하지 않거나 삭제하는 것이 바람직하며, 만일 사용되어야 하는 기능들은 철저한 관리를 통해 사고를 방지해야 한다.

나. 보안 대책

운영중인 웹서버에서 사용하고 있는 웹서버, WAS, Database, 기타 Third party 제품군을 파악하고 각 제품별로 디폴트로 설치되는 기능들 중에서 불필요한 기능이 있는지 검토하여 삭제하도록 한다.

11. 백업 파일

가. 취약점 상세 내용 및 보안 대책

웹 디렉토리 내에 백업용 압축파일, 테스트 파일 등이 존재하고 유추 가능한 이름으로 되어 있는 경우, 별도의 과정 없이 다운로드가 가능하거나 내용이 브라우저 상으로 출력될 수 있으므로 이를 통해서 중요한 정보가 노출될 위협이 있음.

나. 보안 대책

아래의 내용을 확인하고 해당 사항이 발견될 경우, 적절한 조치를 취애햐 함.

12. 에러 페이지 미비

가. 취약점 상세 내용 및 보안 대책

공격자가 대상 시스템의 현황을 파악하기 위하여 다양한 에러를 유발시킴으로써 반응하는 에러 결과값으로 웹 프로그램의 구조 및 환경설정을 추측하여 공격에 이용되므로 이러한 Error를 위한 별도의 페이지를 작성하여 Error발생시 기본 Error Page로 Redirect 시킴으로써, 불필요한 정보가 노출되지 않도록 해야 함. SQL Injection 공격으로 대상시스템의 SQL Query문장의 구성을 알아내기 위한 Foot Printing 시도와 같은 것이 이 항목에 해당됨

나. 보안 대책

모든 에러(404 error,403 error,500 error, …)발생 시 에러 메시지를 외부에 제공하지 않도록 함. 에러가 발생한 경우 에러 발생 메시지를 사용자 클라이언트의 브라우저에 표시하지 않게 하고 메인 페이지 또는 별도로 만든 에러 페이지로 Redirect 시키도록 함.

Apache 에러페이지 설정
# 사용자 정의 에러 반응 메시지 (아파치 스타일)
# 다음 3 가지 방법으로 가능함.
#
# 1) 보통의 텍스트
#ErrorDocument 500 "The server made a boo boo.
# 주목: " 표시는 텍스트임을 알려주는 것으로서 그 자체는 출력되지 않음.
#
# 2) 지역적인 방향 전환
#ErrorDocument 404 /missing.html
# 지역적 URL인 /missing.html로 방향 전환하기
#ErrorDocument 404 /cgi-bin/missing_handler.pl
# 주목: 스크립트나 SSI로 방향 전환시킬 수 있음.
#
# 3) 외부 방향 전환
#ErrorDocument 402 http://some.othercom.com/subscription.html
# 주목: 원래 요청과 관련있는 환경 변수의 상당수가 스크립트에 전달되지 못함.
내부 방향 전환에는 전혀 이상이 없으나 외부 방향 전환 시 가끔 에러가 발생 함.
ErrorDocument 400 /message/400error.html
ErrorDocument 401 /message/401error.html
ErrorDocument 403 /message/403error.html
ErrorDocument 404 /message/404error.html
ErrorDocument 405 /message/405error.html
ErrorDocument 500 /message/500error.html
ErrorDocument 501 /message/501error.html
또는 스크립트를 이용하여 변수를 전달시킬수도 있음.
ErrorDocument 400 /message/error.php?ecode=400
ErrorDocument 401 /message/error.php?ecode=401
ErrorDocument 403 /message/error.php?ecode=403
ErrorDocument 404 /message/error.php?ecode=404
ErrorDocument 405 /message/error.php?ecode=405
ErrorDocument 500 /message/error.php?ecode=500
ErrorDocument 501 /message/error.php?ecode=501

13. 중요정보 전송구간 암호화

가. 취약점 상세 내용 및 보안 대책

인터넷 구간을 통해서 계정 정보나 사용자 정보를 전송할 때 SSL이나 암호화가 적용되지 않은 상태로 전송된다면, 공격자는 인접 네트워크 대역이나 무선 LAN 환경에서 네트워크 트래픽을 모니터링 함으로서 전송되는 정보들을 수집하여 계정 정보나 개인 정보 등 중요 정보를 획득할 수 있다.
만일 암호화나 SSL 이 적용되어 있는 경우에도 안전한 것으로 공인된 강력한 알고리듬이 사용되지 않았거나 SSL 환경 및 인증서 설정의 오류로 인해 취약점이 발생할 수 있다.
또한 많은 웹사이트에서는 퍼포먼스의 문제로 인해서 민감한 정보를 다루는 일부 페이지에서만 SSL 및 암호화를 적용하는데, 민감한 데이터를 전송하면서도 SSL 및 암호화의 적용이 누락되는 페이지가 존재하는 경우가 많기 때문에 보다 철저한 점검이 요구된다.

나. 보안 대책

인터넷 전송 구간을 안전하게 방어하기 위한 가장 쉬운 대책은 웹사이트 전체에 SSL 또는 암호화를 적용하는 것이다. 그러나 퍼포먼스의 문제로 인해서 대부분의 경우 민감한 정보를 다루는 페이지에만 암호화 및 SSL을 적용하게 된다.
웹사이트에서 암호화 및 SSL을 적용할 때는 최소한 다음의 원칙을 준수해야 한다.

14. 사용자 정보 및 기타 중요 정보 노출

가. 취약점 상세 내용 및 보안 대책

웹사이트를 통해서 발생하는 사용자 개인정보 및 중요 정보의 노출은 그 발생 원인이 매우 다양하다. 예를 들면 웹사이트 운영상의 단순한 실수로 정보가 노출되는 경우도 있고, 또는 웹사이트의 설정상의 오류나 보안 취약점에 대한 공격의 결과로서 정보가 노출되는 유형도 존재할 수 있다.
웹사이트 운영상의 실수로 정보가 노출되는 대표적인 유형을 살펴보면, 관리되지 않고 방치되는 게시판 또는 삭제되지 않은 구 버전 웹사이트, 백업 파일 관리 미흡, 관리자의 실수로 업로드된 엑셀 파일 또는 게시물, 비공개 게시물이 설정 실수로 인해 전원에게 공개되는 경우 등을 들 수 있다.
또한 웹사이트 설정 오류나 보안 취약점에 의해 발생하는 유형으로는 암호화가 미흡하거나 파일 업로드 취약점이나 파일 다운로드 취약점을 통해 서버측의 리소스가 직접 유출되는 경우, 디렉토리 인덱싱에 의해 파일 목록이 유출되는 경우, 파라미터 변조 취약점 등에 의해서 발생하는 경우, SQL Injection 등을 통해 DB 데이터가 직접 유출되는 경우도 존재할 수 있다.
따라서 이를 해결하기 위해서는 운영 담당자의 상시 웹사이트 점검 노력과 보안 취약점의 제거 대책이 종합적으로 적용되어야 할 것이다.

나. 보안 대책

웹사이트 운영 담당자는 다음과 같은 내용을 상시 점검해야 한다.

또한 사회 공학적 유형의 정보 유출이 발생하지 않도록 다음과 같은 정책의 적용해야 한다.

15. 관리자 페이지 접근

가. 취약점 상세 내용 및 보안 대책

관리자 기능이 일반 사용자 기능과 분리되어있지 않을 경우, 해당 기능의 경로가 노출되기 쉬우며, 노출된 경로를 통해서 일반 사용자의 접근 시도가 발생하거나 또는 악의적인 공격자에 의한 계속적인 공격을 유발할 수 있음.
관리자 페이지는 적절한 접근 통제가 이루어져야 하며, 접근 통제 없이 임의의 위치에서 접근 가능할 경우, 해당 경로를 유추하거나 기타 다양한 방법에 의해서 위치가 노출될 수 있으므로 이를 통해서 악의적인 공격자에 의한 brute force 공격 등이 발생할 수 있음.

나. 보안 대책

관리자 페이지는 다음과 같은 보안 정책에 의해서 보호되어야함.

추측가능한 관리자 페이지 예
http://www.abc.com/admin.html
http://www.abc.com/admin_main.html
http://www.abc.com/admin/index.html
http://www.abc.com/admin/login.html
http://www.abc.com/master.html
http://www.abc.com/master/index.html

16. WebDAV 취약점

가. 취약점 상세 내용 및 보안 대책

윈도우 서버 컴퓨터에서 기본으로 설치되는 원격관리기능인 WebDAV가 계속 사용가능하도록 설정되어 있고, WebDAV 라이브러리 파일의 속성 및 홈페이지 디렉토리에 쓰기 권한이 모두 허용되어 있는 경우에 해커가 WebDAV 도구를 사용, 원격에서 홈페이지 디렉토리에 임의의 파일을 삽입하여 화면을 변조할 수 있다.

나. 보안 대책

만약 원격 웹 서버 관리를 하지 않는다면 반드시 웹데브 기능을 중지시켜야 한다. 웹데브는 앞서 설명한 취약점 외에도 버퍼오버플로 취약점 등이 존재하여 단지 웹데브 기능이 ‘사용가능’ 상태로 되어 있는 것만으로도 문제가 될 수 있다.

(1) IIS 를 사용하지 않을 경우
(2) IIS 를 사용하는 경우
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W3SVC\Parameters
값 이름: DisableWebDAV
데이터 형식: DWORD
값 데이터: 1

17. 검색 엔진 중요정보 노출

가. 취약점 상세 내용 및 보안 대책

Google 같은 검색엔진의 검색 결과는 해당 검색 엔진의 데이터베이스에 저장되거 유지되기 때문에 중요 정보가 검색 엔진의 검색 결과에 일단 노출이 되면 자신의 웹사이트에서 해당 정보를 삭제해도 검색엔진의 검색 결과에는 일정 기간 정보가 계속 남아있어 유출이 계속 발생하게 된다.
따라서 중요한 정보는 반드시 인증을 거쳐아먄 접근할 수 있는 페이지에 게시하여 검색엔진에 의해서 임의로 정보가 유출되지 않도록 주의해야 하며, 노출된 것으로 확인된 정보는 해당 검색엔진에 직접 정보를 삭제해줄 것을 요구해야 한다.
또한 주기적으로 웹사이트의 URL 및 중요정보의 keyword를 조합하여 검색엔진의 검색 결과를 점검해보고 노출되어서는 안되는 정보가 검색엔진에 노출되어 있는지 여부를 확인하도록 한다.
노출되기 원하지 않는 정보에 대해서는 robots.txt 파일을 설정을 통해 검색을 거부하도록 한다.

나. 보안 대책

(1) 검색엔진에 노출된 중요 정보의 삭제

검색 엔진에 중요 정보가 노출되어 있을 경우, 자신의 웹사이트에서 정보를 삭제해도 검색엔진에는 일정기간 동안 검색 결과가 유지되므로 해당 검색엔진에 내용의 삭제를 직접 요구하도록 한다.

(2) 검색엔진에 의한 검색을 방지하기 위한 설정
* robots.txt 설정

Google, Naver, Daum 등 대부분의 검색엔진은 robots.txt 파일에 의한 검색 거부 규약을 지키고 있으므로 규약에 맞게 robots.txt 파일을 작성하여 적용하면 검색엔진에 노출되는 것을 원치 않는 URL에 대해서 검색을 거부할 수 있다.
robots.txt 작성 방법은 아래와 같다.

모든 검색엔진이 자신의 웹사이트 검색을 금지함
User-agent: *
Disallow: /
모든 검색엔진에게 자신의 특정 디렉토리에 대한 검색을 금지함
User-agent: *
Disallow: /my_directory1/
Disallow: /my_directory2/my_directory3
특정 검색엔진이 자신의 웹사이트를 검색하는 것을 금지함
User-agent: Googlebot
Disallow: /

robots.txt 작성할 때는 다음 사향에 주의하도록 한다.

* 메타 태그 설정 (특정 페이지에 대한 검색 거부)

메타 태그를 이용하면 특정 페이지에 대한 정보 수집을 거부할 수 있다. 메타 태그를 사용하기 위해서는HTML의 <head> 태그 사이에 다음 구문을 삽입한다.

<meta name="robots" content="noindex, nofollow">
Google 에서 검색결과 테스트

자신의 사이트의 주요 정보가 검색엔진에 노출되어있는지 테스트하기 위해서 다음과 같은 유형의 검색 keyword를 통해서 주기적으로 검색 결과를 점검하도록 한다.

Google 검색 키워드 예시
- inurl:www.myweb.co.kr filetype:doc
- inurl:www.myweb.co.kr 고객명단
- inurl:www.myweb.co.kr admin

18. 특수 문자 취약점

가. 취약점 상세 내용 및 보안 대책

웹서버 및 WAS는 제품과 버전에 따라 ‘Null’, ‘%00’, ‘%3f’, ‘#’, ‘::’ 등과 같은 특수 문자의 처리시 발생하는 버그로 인해 요청된 URL 의 소스 코드를 노출시키거나 디렉토리 목록 등을 출력하는 문제가 과거 여러 차례 보고된 바 있다.
따라서 웹사이트 운영 담당자는 담당 웹사이트에서 사용하고 있는 제품의 Vendor에서 제공하는 패치 정보 및 보안 권고문을 항상 확인하도록 하고, 보안 이슈 사항에 대해서 자신의 서버가 영향이 있는지를 테스트하여 적절한 보안 대책을 적용하도록 한다.
또한 자신이 운영하고 있는 웹사이트가 과거에 발생했던 특수 문자 처리 취약점의 영향을 받고 있는지를 테스트하여 만일 취약점을 갖고 있다면 이를 즉시 해결해야 한다.

나. 보안 대책

아래 사항을 점검 후, 취약한 것으로 확인된 경우는 자신의 Vendor 사의 보안 권고문을 확인하고 지시에따라 보안 패치를 설치하거나 웹서버 또는 WAS의 설정을 변경한다.

* Resin 2.x 이전 버전 / 기타 java 기반 웹 애플리케이션 서버 공통

아래와 같이 입력시 디렉토리 목록을 출력

* JEUS

아래와 같이 입력시 요청 URL의 소스코드 또는 디렉토리 목록을 출력

아래와 같이 입력시 URL의 소스코드를 출력

* 플랫폼 공통

다음과 같은 특수문자가 삽입된 URL 을 테스트하여 웹서버의 반응을 확인한 후, 정상적인 400, 403, 404, 500 error가 아닌 특수한 반응(예: 소스코드 출력 또는 디렉토리 목록 출력)이 발생하는 경우, Vendor사의 보안 권고문에서 해당 내용을 검색하여 지시에 따라 대책을 적용해야 한다.

테스트할 특수문자 목록
테스트할 특수문자 목록 : [.], [%2E], [+], [%2B], [%2A], [\], [%5C], [?], [%3F], [%20], [%00]

테스트할 URL 패턴은 다음의 두가지 케이스를 테스트한다. (예: %2E를 테스트 할 경우)